算是读书笔记吧
极客时间--设计模式之美
开闭原则 -- OCP(Open Closed Principle)
software entities (modules, classes, functions, etc.) should be open for extension , but closed for modification
软件实体(模块、类、方法等)应该“对扩展开放、对修改关闭”
对拓展开放是为了应对变化(需求),对修改关闭是为了保证已有代码的稳定性。
举个几个最简单的反例:如果你的方法的具体行为,有很多地方耦合这各种基于业务类型的if/else,那么他一定是违反开闭原则的。
void calloutMethod {
if (type == ModeA) {
//打电话
} else (type == ModeB) {
//发短信
} else (type == ModeC) {
//发视频
}
}
void doneMethod {
if (type == ModeA) {
//打电话结束
} else (type == ModeB) {
//发短信结束
} else (type == ModeC) {
//发视频结束
}
}
void comingCallMethod {
if (type == ModeA) {
//收到电话
} else (type == ModeB) {
//收到短信
} else (type == ModeC) {
//收到视频
}
}
上面的例子做了很多简化,一旦代码复杂起来。如果我们想要开发一个新的功能,或者对某个功能做定制,就无法保证对其他功能没有影响。
void configXXXX() {
//基本操作...
}
//修改后
void configXXXX(isModeA , isModeB) {
//基本操作...
if (isModeA) {
//特殊操作...
}
//基本操作...
if (isModeB) {
//特殊操作
}
//基本操作...
if (isModeA && !isModeB) {
//特殊操作...
} else if (isModeA){
//特殊操作...
}
//基本操作...
}
这个情况对于很多开发人员都很常见,尤其在修改迭代他人代码的时候。
这种打补丁的方式,随着补丁的增多,对项目也是毁灭性的。
-
修改和扩展
- 开闭原则并不是说完全杜绝修改
有些功能无论你怎样设计,都难免要面临修改。所以我们要尽量以最小的修改代码的代价来完成新功能的开发。
比如修改方法内部的逻辑。无论你如何设计,都要牵扯到回归测试。
- 修改的定义,有时也很主观
同样的代码改动,在粗代码粒度下,可能被认定为“修改”;在细代码粒度下,可能又被认定为“扩展”。
比如在模块内添加一个属性,以满足新业务需要。这个操作对于类,属于修改。对于该类的使用方,属于扩展。
如果你要修改一处代码,更落地、更容易量化的标准是:
只要它没有破坏原有的代码的正常运行,没有破坏原有的单元测试,我们就可以说,这是一个合格的代码改动。
-
开闭原则的扩展性是很多设计思想、模式的指导思想与最终目的
多态、依赖注入、基于接口而非实现编程,以及大部分的设计模式(比如,装饰、策略、模板、职责链、状态)。