设计模式6大原则你真的懂了吗?
Contents
前面的文章讲述了设计模式的3大类型,下面讲述一下设计模式遵循的6大原则
单一职责原则
-
定义
有且只有一个原因引起类的变更
-
优势
类的复杂性降低,任何职责实现都有明确清晰的定义; 可读性提高; 可维护性提高; 变更引起的风险降低。
-
最佳实践
接口,在设计的时候,一定要做到单一。但是,对于接口的实现类需要根据具体业务多方面考虑。 单一职责原则不仅仅适用于接口和类,同时也适用于方法——一个方法尽可能只做一件事情。
-
总结
接口一定要做到单一职责,类的设计尽量做到只有一个原因引起变化。
里式替换原则
-
定义
所有应用基类的地方必须能透明地使用其子类的对象(只要父类能出现的地方子类就可以出现,而且替换为子类也不会产生任何错误或者异常。使用者可能根本不需要知道使用的是父类还是子类)。
-
最佳实践
在类中调用其他类时,务必使用父类或者接口。如果不能使用父类或者接口,说明类的设计已经违背了LSP原则。
如果子类不能完整地实现父类的方法,或者父类的某些方法在子类中已经发生了“畸变”(Override),则建议断开父子的继承关系,而是通过依赖、聚集或者组合等关系代替继承。
覆盖或实现父类的方法时,输入参数可以被放大。即:子类中方法的前置条件(输入参数)必须与超类中被覆写的方法的前置条件相同或者更宽松。
覆写或实现父类的方法时,输出结果可以被缩小。
-
总结
采用里氏替换原则的目的是增强程序的健壮性,版本升级的时候可以保持非常好的兼容性。即使增加了子类,原有的子类还可以继续运行。
依赖倒置原则
-
定义
高层模块不应该依赖低层模块,两者都应该依赖抽象。
抽象不应该依赖细节。
细节应该依赖抽象。
-
最佳实践
依赖倒置原则的本质是通过抽象(接口或者抽象类)使各个类或模块的实现彼此独立,互不影响,从而实现模块间的松耦合。 在具体项目中实现依赖倒置原则,需要遵循以下几个规则:
每个类尽量都有接口或者抽象类,或者接口和抽象类两者都具备。这是依赖倒置原则的基本要求,抽象和接口类属于抽象的,有了抽象才能实现依赖倒置。
变量的表面类型尽量使接口或者抽象类。特例:如果需要使用类的clone方法,就必须使用实现类(JDK的规范)。
任何类都不应该从具体类派生。
尽量不要覆写积累的方法。如果基类是一个抽象类,并且某个方法已经实现了,那么子类尽量不要覆写。类间依赖的是抽象,如果覆写了抽象的某个方法,对依赖的稳定性会产生一定影响。 结合里氏替换原则使用
接口负责定义public属性和方法,并且声明与其它对象的依赖关系;抽象类负责公共部分的实现;实现类准确实现业务逻辑,同时在适当的时候对父类进行细化。
依赖倒置原则是实现开闭原则的重要途径,也是六大原则中最难以实现的原则。如果依赖倒置原则没有实现,就难以实现开闭原则(对扩展开放,对修改关闭)。
接口隔离原则
-
定义
定义一: 客户端不应该依赖它不需要的接口。
定义二: 类间的依赖关系应该建立在最小的接口上。
也就是说,应该建立单一接口,不要建立臃肿庞大的接口。接口尽量细化,同时接口中的方法尽量少。
要注意与单一职责原则的区分,两者角度不同。单一职责原则要求类和接口职责单一,注重的是职责,是业务逻辑上的划分;接口隔离原则要求接口的方法尽量少
-
最佳实践
接口隔离原则是对接口和类的定义,接口和类尽量使用原子接口或原子类来组装。这个“原子”的划分,可以通过以下几个规则来衡量:
一个接口只负责一个子模块或业务逻辑。
通过业务逻辑压缩接口中的public方法。
已经被污染了的接口,尽量去修改。若变更风险较大,则采用适配器模式进行转化处理。
了解应用场景,不要盲从。场景不同,接口拆分的标准就不同。根据应用场景和自己的经验、常识,合理确定接口粒度大小。
迪米特原则
-
定义
一个对象应该对其他对象有最少的了解。因此又称为最少知识原则(Least Knowledge Principle, LKP)。
在迪米特原则中,一个类只和朋友类交流。朋友类:出现在成员变量、方法的输入输出参数中的类,称为成员朋友类,而出现在方法内部的类不属于朋友类。
如果一个方法放在本类中,既不增加类间关系,也不对本类产生负面影响,就放在本类中。
迪米特法则要求类尽量不要对外公布太多的public方法和非静态的public变量,尽量内敛,多使用private、package-private(default)、protected等访问权限。
-
最佳实践
迪米特原则的核心理念就是:类间解耦,弱耦合,从而提高类的复用率。结果是:产生了大量中转或者跳转类,导致系统复杂性提高,可维护性降低。
使用迪米特原则,要反复权衡,既做到结构清晰,又做到高内聚低耦合。
开闭原则
-
定义
一个软件实体(类、模块和防暑等)应该对扩展开放,对修改关闭。也就是说,一个软件实体通过扩展来实现变化,而不是通过修改原来的代码来实现变化。开闭原则是对软件实体的未来事件而制定的对现行开发设计进行约束的一个原则。
软件实体:
-
项目或软件产品中按照一定的逻辑规则划分的模块
-
抽象或类
-
方法
-
-
最佳实践
1 抽象约束
要实现对扩展开放,首要的前提条件是抽象约束。接口或抽象类可以约束一组可能变化的行为,并且能够实现对扩展开放。抽象约束包含3层含义:
-
约束扩展边界
通过接口或抽象类约束扩展,对扩展进行边界限定,不允许出现在接口或抽象类中不存在的public方法。
-
约束参数类型 应用参数对象尽量使用接口或者抽象类,而不是实现类。
-
抽象层尽量保持稳定
抽象层一旦确定,就不再允许修改。
2 元数据(metadata)控制模块行为
元数据:用来描述环境和数据的数据,也就是配置参数。配置参数可以来自配置文件,也可以来自数据库。
使用元数据来控制程序的行为,可以减少重复开发。
3 制定项目章程(约定优于配置)
团队中应该有所有成员都必须遵守的开发约定。约定可以提高开发效率和沟通效率。
4 封装变化
封装变化有两层含义:
- 将相同的变化封装到一个接口或抽象类中;
- 将不同的变化封装到不同的接口或抽象类中。
-
参考: 设计模式6大原则@简书.Jerry_1116
Author ai0376
LastMod 2020-01-16