0x01.开闭原则
定义:一个软件实体如: 类,模块和函数应该对扩展开放,对修改关闭 【可以通过扩展实现新功能,不能通过修改抽象类/基类来达到修改的目的】
要点:
- 当变更发生时,不要直接修改类,而是通过继承扩展的方式完成变更
- 用抽象构建框架,用实现扩展细节
- 预先设计好抽象
优点:提高软件系统的可复用性及可维护性
- 面向抽象编程,实现抽象化,抽象出业务模型
- 提高内聚,降低耦合
https://www.jianshu.com/p/5f1dc9f7b57d
开放-关闭原则 Open Close Principle
软件实体,如类、模块和函数,应该对扩展开放,对修改关闭。
OPC 是一个通用原则。
你可以在这种情景下考虑此原则:当你构建类的时候,你想要确保以后你要扩展类行为时只需扩展它而不需要修改原类。
这原则同样适用于模块、包和代码库。
如果你手头一个包含多个类的代码库,大多数情况下你更愿意去扩展它,也不想去修改已有的代码(向后兼容,回归测试等)。
这就是为什么我们必须确保我们的模块遵循开放-关闭原则的原因。
当提及类时,开放-关闭原则可以通过使用抽象类+实现类来实现他们的行为。
这会强制使用具体实现类来扩展抽象类而不去修改抽象类。具体的实例有:模版模式、策略模式。
https://blog.csdn.net/fengchao2016/article/details/54378113
客户的需求是不稳定的,通过扩展已有的软件系统而不是通过修改软件系统来满足客户的需求,这样的软件系统就满足开-闭原则,即软件系统要有一定的灵活性和适应性。
已有的模块,特别是抽象层的模块不能修改,保证软件系统的稳定性和延续性。
解决问题的关键是抽象化,把它与具体实现分离开来。
实现开闭原则的关键:
抽象化是解决问题的关键,在面向对象的编程语言里,可以给系统定义出一套相对较为固定的抽象设计,此设计允许无穷无尽的行为在实现层被实现。
在语言里,可以给出一个或多个抽象类或者接口,规定出所有的具体类必须提供的方法的特征作为系统设计的抽象层。
这个抽象层预见了所有的可扩展性,因此,在任何扩展情况下都不会改变。这就使得系统的抽象不需要修改,从而满足了开闭原则的第二条,对修改关闭。
同时,由于从抽象层导出一个或多个新的具体实现类可以改变系统的行为,因此系统的设计对扩展是开放的,这就满足了开闭原则的第一条。
对可变性的封装原则:
这是对开闭原则的另外一种描述,它讲的是找到一个系统的可变因素,将之封装起来。该原则意味着两点:
①一种可变性不应当散落在代码的很多角落,而应当封装到一个对象里面。继承应当被看做是封装变化的方法,而不应该被认为是一种从一般对象生成特殊对象的方法。
②一种可变性不应当与另外一种可变性混合在一起。这意味着一般的继承层次不会超过两层。
有一个图表打印的模型,可以打印出饼图,条形图......
一个不合格开闭原则的设计模型图如下:
package principle; public class ChartDisplay { public void diaplay(String type) { if("pie".equals(type)) { PieChart dis = new PieChart(); dis.display(); } else if ("bar".equals(type)) { BarChart dis = new BarChart(); dis.display(); } } } package principle; public class PieChart extends ChartDisplay { public void display() { System.out.println("pie......."); } } package principle; public class BarChart extends ChartDisplay { public void display() { System.out.println("bar......"); } }
显然如果在要有一个打印其他图像的类进行扩展,则需要修改ChartDisplay类中的内容,显然不合适,这么设计是有问题的。
正确的是code如下:
package principle1; public abstract class AbstractChart { abstract void display(); } package principle1; public class BarChart extends AbstractChart { public void display() { System.out.println("bar......"); } } package principle1; public class PieChart extends AbstractChart { @Override public void display() { System.out.println("pie......."); } }
引入了一个抽象类,这种写法有点类似与抽象工厂模式。
————————————————
http://www.cnblogs.com/muzongyan/archive/2010/08/05/1793454.html
开闭原则(Open Closed Principle)是Java世界里最基础的设计原则,它指导我们如何建立一个稳定的、灵活的系统。
定义:
一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
Softeware entities like classes,modules and functions should be open for extension but closed for modifications.
开闭原则的含义是说一个软件实体应该通过扩展来实现变化,而不是通过修改已有代码来实现变化。
软件实体包括以下几个部分:
- 项目或软件产品中按照一定的逻辑规则划分的模块
- 抽象和类
- 方法
开闭原则是为软件实体的未来事物而制定的对现行开发设计进行约束的一个原则。
注意:开闭原则对扩展开放,对修改关闭,并不意味着不做任何修改,低层模块的变更,必然要有高层模块进行耦合,否则就是一个孤立无意义的代码片段了。
变化的类型:
- 逻辑变化
- 子模块变化
- 可见试图变化
一个项目的基本路径应该是这样的:项目开发、重构、测试、投产、运维,其中的重构可以对原有的设计和代码进行修改,运维尽量减少对原有代码修改,保持历史代码的纯洁性,提高系统的稳定性。
开闭原则的重要性:
- 开闭原则对测试的影响
开闭原则可是保持原有的测试代码仍然能够正常运行,我们只需要对扩展的代码进行测试就可以了。
- 开闭原则可以提高复用性
在面向对象的设计中,所有的逻辑都是从原子逻辑组合而来的,而不是在一个类中独立实现一个业务逻辑。只有这样代码才可以复用,粒度越小,被复用的可能性就越大。
- 开闭原则可以提高可维护性
- 面向对象开发的要求
如何使用开闭原则:
- 抽象约束
第一,通过接口或者抽象类约束扩展,对扩展进行边界限定,不允许出现在接口或抽象类中不存在的public方法;
第二,参数类型、引用对象尽量使用接口或者抽象类,而不是实现类;
第三,抽象层尽量保持稳定,一旦确定即不允许修改。
- 元数据(metadata)控制模块行为
元数据就是用来描述环境和数据的数据,通俗地说就是配置参数,参数可以从文件中获得,也可以从数据库中获得。
Spring容器就是一个典型的元数据控制模块行为的例子,其中达到极致的就是控制反转(Inversion of Control)
- 制定项目章程
在一个团队中,建立项目章程是非常重要的,因为章程中指定了所有人员都必须遵守的约定,对项目来说,约定优于配置。
- 封装变化
对变化的封装包含两层含义:
第一,将相同的变化封装到一个接口或者抽象类中;
第二,将不同的变化封装到不同的接口或抽象类中,不应该有两个不同的变化出现在同一个接口或抽象类中。