开放封闭原则
开放封闭原则(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);
}
}