一、单一职责原则
单一职责原则的英文名称是single responsibility principle,简称SRP。单一职责原则就是类或接口内功能的单一化,降低之间的耦合度,增强程序的健壮。
书中总结单一职责原则的好处:
- 类的复杂性降低,实现什么职责都有清晰明确的定义
- 可读性提高,因为复杂性降低
- 可维护性提高,因为可读性提高
- 变更引起的风险降低,变更是必不可少的,如果接口的单一职责做得好,一个接口的修改只对实现类有影响,对其他接口无影响,这对系统的扩展性、维护性都有非常大的帮助
真要实现类的单一职责,这会引起类间耦合过重,类的数量增加等问题。所以类的单一职责确实受很多因素的制约,纯理论来讲,这个原则非常优秀,但是现实有现实的难处,要完全遵守很难做到。
书作者建议:接口一定要做到单一原则,类的设计尽量做到只有一个原因引起变化。
本章作者提到方法的单一职责,列举用户信息修改实例:用户信息修改功能要分解成用户名称修改,密码修改,地址修改三个功能,这样体现方法的单一职责原则。
但是实际项目中,存在可以同时修改用户名称,密码和地址的情况,这时该如何设计用户信息修改功能呢?
二、里氏替换原则
定义:英文缩写为LSP。所有引用基类的地方必须能透明的使用其子类的对象。通俗点讲,只要父类能出现的地方子类就能出现,而且替换为子类也不会产生任何错误或异常, 使用者可能根本就不需要知道是父类还是子类。但是,反过来就不行,有子类出现的地方,父类未必就能适应。
继承的优点:
- 代码共享,减少创建类的工作量
- 提高代码的重用性
- 子类可以形似父类,但又异于父类
- 提高代码的可扩展性
- 提高产品或项目的 开放性
继承的缺点:
- 继承是侵入性的。只要继承,就必须拥有父类的所有属性和方法
- 降低代码的灵活性
- 增加了耦合性。父类的常量,变量和方法被修改时,需要考虑子类的修改。
里氏替换原则为良好的继承定义了一个规范,一句简单的定义包含了4个层次。
- 子类必须完全实现父类的方法
注意:在类中调用其他类时务必要使用父类或接口,如果不能使用父类或接口,说明类的设计已经违背了LSP原则
注意:如果子类不能完整实现父类的方法,或父类的某些方法在子类中已经发生畸变,则建议断开父子继承关系,采用依赖, 聚集,组合等关系代替继承
- 子类可以有自己的个性(在满足第一条前提下,可以扩展其他功能...)
- 覆盖或实现父类的方法时输入参数可以被放大
- 覆盖或实现父类的方法时输出结果可以被缩小
书作者建议:在项目中,采用里氏替换原则时,尽量避免子类的个性,一旦子类有个性,这个类和父类之间的关系很难被调和了,把子类当做父类使用,子类的个性被抹杀;把子类单独做一个业务来使用,则让代码间的耦合关系变的扑朔迷离--缺乏类替换的标准
三、依赖倒置原则
依赖倒置原则,Dependence Inversion Principle, DIP,包含三层含义:
- 高层模块不应该依赖底层模块,两者都应该依赖于抽象
- 抽象不应该依赖细节
- 细节应该依赖抽象
依赖导致在JAVA中的表现是:
- 模块间的依赖通过抽象发生,实现类间不发生直接的依赖关系,其依赖关系是通过接口或抽象类实现的
- 接口或抽象类不依赖于实现类
- 实现类依赖接口或抽象类
更精简的定义是面向接口编程(OOD - Object-Oriented Design)
依赖的三种写法:
- 构造函数传递依赖对象
- setter方法传递依赖对象
- 在接口声明依赖对象,该方法叫做接口注入
书作者建议:
- 每个类尽量都要有接口或抽象类,或者抽象类和接口同时具备
- 变量的表面类型尽量使接口或抽象类
- 任何类都不应该从具体类中诞生
- 尽量不要覆盖基类的方法
- 结合里氏替换原则使用
名词:开闭原则,对扩展开发,对修改关闭。
四、接口隔离原则
定义:建立单一接口,不要建立臃肿庞大的接口,通俗讲:接口尽量细化,同时接口中的方法计量少。
接口隔离原则与单一职责原则的区别?
答案:接口隔离原则与单一职责的审视角度不同,单一职责要求是类和接口职责单一,注重是职责,这是业务逻辑上的划分。而接口隔离原则要求接口的方法尽量少。
接口隔离原则是对接口进行规范约束,其包含以下4层含义:
- 接口要尽量小(根据接口隔离原则拆分接口时,首先必须满足单一职责原则)
- 接口要高内聚
什么事高内聚?高内聚就是提高接口、类、模块的处理能力,减少对外的交互。
- 定制服务
- 接口设计师有限度的
接口的设计粒度越小,系统越灵活,这是不争的事实。但是,灵活的同时也带来了结构的复杂化,开发难度增加,可维护性降低,所以接口一定要适度,这个度要考靠经验和尝试判断...........................
书作者建议:
- 一个接口只服务于一个子模块或业务逻辑
- 通过业务逻辑压缩接口中的public方法
- 已经被污染的接口,尽量去修改,若变更风险太大,则采用适配器模式转化处理
- 了解环境,拒绝盲从。
五、迪米特法则
定义:Law of Demeter, LoD 也称为最少知识原则。
迪米特法则对类的低耦提出了明确的要求,包含以下4层含义:
- 只和朋友交流
什么叫直接朋友?两个对象之间的耦合叫朋友关系。
注意,一个类只和朋友交流,不与 陌生类交流,不要出现getA().getB().getC().getD()这种情况,类与类之间的关系是建立在类间的,而不是方法间,因此一个方法尽量不引入一个类中不存在的对象。
- 朋友间也是有距离的
迪米特法则要求类“羞涩”一点,尽量不要对外公布太多的public方法和非静态的public变量,尽量内敛,多使用private, package-private, protected等访问权限
- 是自己的就是自己的
在实际应用中经常会出现这样一个方法:放在本类中也可以,放在其他类中也没有错,那怎么去 衡量呢?你可以坚持这样一个原则:如果一个方法放在本类中,既不增加类间关系,也对本类不产生负面影响,那就放置在本类中。
- 谨慎使用Serializable
书作者建议:
迪米特法则的核心观点是类间解耦,弱耦合,只有弱耦以后,类的复用率才可以提高。
六、开闭原则
定义:一个软件实体如类,模块和函数应该对扩展开放,对修改关闭。
软件实体包括以下几部分:
- 项目或软件产品中按照一定的逻辑规则划分的模块
- 抽象和类
- 方法