开闭原则:(一个软件实体如类,模块和函数应该对扩展开放,对修改关闭)开闭原则要求尽量通过扩展软件实体的方法来适应变化,而不是通过修改已有的代码来完成变化。它是为软件实体的未来而制定的对现行开发设计进行约束的一个原则。
简单例子:以图书销售为例,图书有三个属性,价格,书名以及作者。小说书继承了图书接口。如果有一天图小说书打折,修改方案有三种:
(1)修改图书接口,在接口中增加获得打折价格方法。缺点是所有实现图书的接口都需要增加这种方法。
(2)直接修改小说类中获得价格的方法。缺点是:无论谁都看不到小说书的原价。
(3)新写一个打折小说类,继承小说类,覆写其中的价格方法。销售时,将打折小说类赋给图书接口。采购人员查看价格时,可以通过常见小说类实现。
变化分类:我们把变化分为三种。
(1)逻辑变化 只变化一个逻辑,不涉及其它模块。可以通过修改类中的方法来完成。前提条件是所有依赖或者关联的类都按照相同的逻辑处理。
(2)子模块变化 一个子模块变化,会引起高层的变化。因此通过扩展完成变化时,高层次的模块修改也是必然的。
(3)可见视图的变化
如何应用开闭原则:
(1)抽象约束通过接口或者抽象类可以约束一组可能变化的行为,并且能够实现对扩展开放。包含三层和含义:
第一,通过接口和抽象类约束扩展,多扩展进行边界限定,不允许出现在接口或者抽象中不存在的接口。
第二,参数类型,引用对象尽量使用接口或者抽象类,而不是实现类。
第三,抽象层尽量保持稳定,一旦确定即不允许修改。如果因业务需要增加新的功能,可以写一个继承原有接口的接口。
(2)通过元数据控制模块行为 元数据用来描述环境和数据的数据,通俗的说就是配置参数,参数可以从文件中获得或者数据库中获得。
(3)封装变化 预测将来可能出现的变化,将相同的变化封装到一个接口或者抽象类中,将不同的变化封装到不同的接口后者抽象类中。
1、设计软件要容易维护又不容易出问题的最好的办法,就是多扩展,少修改。
2、无论模块是多么的“封闭”,都会存在一些无法对之封闭的变化。既然不可能完全封闭,设计人员必须对于他设计的模块应该对哪种变化封闭做出选择。他必须先猜测出最有可能发生的变化各类,然后构造抽象来隔离那些变化。
在开发程序时,我们可能是很难预先猜测的,但我们却可以在发生小变化时,就及早去想办法对发生更大变化的可能。也就是说,等到变化发生时立即采取行动。
3、我们最初编写代码时,可以假设变化不会发生。当变化发生时,我们就创建抽象来隔离以后发生的同类变化。
面对需求,对程序的改动是通过增加新代码进行的,而不是更改现有的代码。
4、开放-封闭原则是面向对象设计的核心所在。遵循这个原则可以带来面向对象技术所声称的巨大好处,也就是可维护、可扩展、可利用、灵活性好。
5、开发人员应该只对程序中呈现出频繁变化的那些部分做出抽象,然而,对于应用程序中的每个部分都刻意地进行抽象同样不是一个好主意。拒绝不成熟的抽象和抽象本身一样重要。