1.前言
在软件开发中,为了提高软件系统的可维护性和可复用性,增加软件的可扩展性和灵活性,程序员要尽量根据原则来开发程序,从而提高软件开发效率、节约软件开发成本和维护成本。首先介绍下什么是开闭原则?
2.概念
开闭原则(Open closed principle,OCP)由勃兰特·梅耶(Bertrand Meyer)提出,软件实体应当对扩展开放,对修改关闭(Software entities should be open for extension,but closed for modification),这就是开闭原则的经典定义。
3.作用
对软件测试的影响软件遵守开闭原则的话,软件测试时只需要对扩展的代码进行测试就可以了,因为原有的测试代码仍然能够正常运行。
可以提高代码的可复用性粒度越小,被复用的可能性就越大;在面向对象的程序设计中,根据原子和抽象编程可以提高代码的可复用性。
可以提高软件的可维护性遵守开闭原则的软件,其稳定性高和延续性强,从而易于扩展和维护。
4.实现方法
可以通过“抽象约束、封装变化”来实现开闭原则,即通过接口或者抽象类为软件实体定义一个相对稳定的抽象层,而将相同的可变因素封装在相同的具体实现类中。
5.实例
场景: 你是个书店老板,你现在刚到了一本好书(java),你想打折出售,但是我只是针对我这本书打折,其他的不想打折,可能以后的话,也想其他的书也打折,或者过几天我又想让这本书恢复原价(看我心情)
按需求画出类图
创建一个抽象类Book,里面有一些通用方法和属性,和一个抽象的打折(dicount)方法(因为每本书的打折不一样), 然后用java类(目前老板只想让java这本书打个8折)去继承抽象类Book并实现打折(dicount)方法,这样设计就实现了开闭原则,如果下次想别的书(typeScript)打折,是不是不需要改以前的代码,只需要新增一个typeScript类就可以了?又或者我过两天我又想让java书恢复原价,是不是直接调用getPrice就可以了!
1.首先创建一个抽象类Book
//Book.ts
export abstract class Book {
public name: string;
public price: number;
constructor(name: string, price: number) {
this.name = name;
this.price = price;
}
public getPrice(): number {
return this.price;
}
public getName() {
return this.name;
}
//抽象方法
abstract discount(): number;
}
2.然后实现子类
//java.ts
import { Book } from "./Book"
export class java extends Book {
constructor(name:string,price:number) {
super(name, price);
}
public discount(): number {
return this.getPrice() * 0.8;
}
}
//typeScript.ts
//再实现个typeScript类,并且他的打折方式也不一样, (满50减10元,满30减5元 否则减2元)
import { Book } from "./Book"
export class typeScript extends Book {
constructor(name: string, price: number) {
super(name, price);
}
public discount(): number {
//满50减10元,满30减5元 否则减2元
let price = this.getPrice();
if (price >= 50) {
return price-10;
}else if(price>=30 && price<50){
return price-5;
}else{
return price-2;
}
}
}
3.最后在外层调用
//java的打折
let javaBook = new java('java', 30);
console.log(javaBook.getName()+"价格是"+javaBook.discount()+"元");
//typeScript的打折
let typeScriptBook = new typeScript("typeScript",40);
console.log(typeScriptBook.name+"价格是"+typeScriptBook.discount()+"元");
//恢复java原价
console.log(javaBook.getName()+"价格是"+javaBook.getPrice()+"元");