开放封闭原则

98 阅读1分钟

开放封闭原则

开放封闭原则(Open Close Principle,OCP)

核心思想:对扩展开放,对修改关闭

案例分析:

案例一:

动物园里有很多动物,游客希望观察每一种动物是怎样活动的。

class TerrestrialAnimal {
  constructor(name) {
    this.name = name
  }
  running() {
    console.log(`${this.name} is running`)
  }
}
class AquaticAnimal {
  constructor(name) {
    this.name = name
  }
  swimming() {
    console.log(`${this.name} is swimming`)
  }
}
class Zoo {
  constructor() {
    this.animals = [new TerrestrialAnimal('dog'), new AquaticAnimal('fish')]
  }
  displayActivity() {
    this.animals.forEach(animal => {
      if (animal instanceof TerrestrialAnimal) {
        animal.running()
      } else if (animal instanceof AquaticAnimal) {
        animal.swimming()
      }
    })
  }
}

这个写法不符合开放封闭原则,如果要再加一个类型的动物(如鸟类,而鸟是会飞的),这个时候就又得修改 displayActivity 方法,再增加一个 if… else… 判断。

重新设计,让其满足开放封闭原则。

abstract class Animal {
  constructor(public name) {}
  abstract moving(): void
}
class TerrestrialAnimal extends Animal {
  moving() {
    console.log('I am moving on the ground')
  }
}
class AquaticAnimal extends Animal {
  moving() {
    console.log('I am moving in the water')
  }
}
class AerialAnimal extends Animal {
  moving() {
    console.log('I am moving in the air')
  }
}
class Zoo {
  constructor(public animals: Animal[] = []) {}
  addAnimal(animal: Animal) {
    this.animals.push(animal)
  }
  displayActivity() {
    this.animals.forEach(animal => animal.moving())
  }
}
function test() {
  const lion = new TerrestrialAnimal('lion')
  const fish = new AquaticAnimal('fish')
  const eagle = new AerialAnimal('eagle')
  const zoo = new Zoo()
  zoo.addAnimal(lion)
  zoo.addAnimal(fish)
  zoo.addAnimal(eagle)
  zoo.displayActivity()
}
test()

把各种类型的动物抽象出一个基类——动物类,把动作也抽象成了移动。这样每增加一种类型的动物,只要增加一个 Animal 的子类即可,其他代码几乎可以不用动。要修改一种类型动物的行为,只要修改对应的类即可,其他的类不受影响。这才符合开放封闭原则。

案例二:

考虑一个简单的支付系统,其中有一个PaymentProcessor类用于处理不同类型的支付。如果不使用开放封闭原则,可能会在这个类中通过条件语句来判断和处理不同类型的支付,这会导致每当添加新的支付类型时都需要修改这个类。

type PaymentType = 'creditCard' | 'paypal';
​
class PaymentProcessor {
    processPayment(amount: number, type: PaymentType) {
        if (type === 'creditCard') {
            console.log(`Processing credit card payment: $${amount}`);
            // 信用卡支付逻辑
        } else if (type === 'paypal') {
            console.log(`Processing PayPal payment: $${amount}`);
            // PayPal支付逻辑
        }
        // 每次添加新的支付类型都需要修改这里
    }
}

遵循开放封闭原则,可以定义一个支付接口,让每种支付类型实现这个接口。PaymentProcessor类则通过这个接口处理支付,而不是直接实现所有的支付逻辑。这样,添加新的支付方式时,只需添加新的实现类,而无需修改现有的PaymentProcessor类。

interface PaymentMethod {
    processPayment(amount: number): void;
}
​
class CreditCardPayment implements PaymentMethod {
    processPayment(amount: number) {
        console.log(`Processing credit card payment: $${amount}`);
        // 信用卡支付逻辑
    }
}
​
class PayPalPayment implements PaymentMethod {
    processPayment(amount: number) {
        console.log(`Processing PayPal payment: $${amount}`);
        // PayPal支付逻辑
    }
}
​
class PaymentProcessor {
    processPayment(amount: number, paymentMethod: PaymentMethod) {
        paymentMethod.processPayment(amount);
    }
}