第十五章:面向对象设计原则
LSP(The Liskov Substitution Principle:Liskov替换原则)
- 任意父类可以出现的地方,子类也可以出现
如果在任何情况下,子类(或子类型)或实现类与基类都是可以互换的,那么继承的使用就是合适的。为了达到这一目标,子类不能添加任何父类没有的附加约束
OCP(The Open-Close Principle:开放-封闭原则)
-
对扩展开发,对修改关闭
对于扩展是开放的(Open for extension):模块的行为可以扩展,当应用的需求改变时,可以对模块进行扩展,以满足新的需求
对于更改是封闭的(Closed for modification):对模块行为扩展时,不必改动模块的源代码或二进制代码 -
OCP的关键在于抽象
抽象技术:abstract class, Interface
抽象预见了可能的所有扩展(闭)
由抽象可以随时导出新的类(开) -
LSP是OCP成为可能的主要原则之一
正是子类型的可替换性才使得使用基类类型的模块在无需修改的情况下就可以扩展 -
一个软件系统的所有模块不可能都满足OCP,但是应该努力最小化这些不满足OCP的模块数量。
SRP(The Single Responsibility Principle:单一职责原则)
-
类的职责单一
-
SRP是实现“高内聚、低耦合”的指导方针(内聚性:一个模块的组成元素之间的功能相关性)
ISP(The Interface Segregation Principle:接口隔离原则)
-
使用多个专门的接口比使用单一的接口好
-
客户不应该依赖他们不用到的方法,只给每个客户它所需要的接口
DIP(The Dependency Inversion Principle:依赖倒置原则)
-
针对抽象(或接口)编程,而不针对具体编程
-
高层模块不应该依赖于低层模块。二者都应该依赖于抽象
-
抽象不应该依赖于细节。细节应该依赖于抽象
-
简单来说,依赖倒转原则就是指:代码要依赖于抽象的类,而不要依赖于具体的类;要针对接口或抽象编程,而不是针对具体编程。
-
实现开闭原则的关系是抽象化,并且从抽象化导出具体化实现。如果把OCP看成是面向对象设计的目标的话,那么DIP就是实现该目标的一种主要手段。
传统的依赖关系
符合DIP的系统
CRP(组合聚合原则)
-
优先使用组合或聚合关系,不要过于使用继承关系
-
继承复用:实现简单,易于扩展。破坏系统的封闭性,从基类继承而来的实现是静态的,不能在运行时动态改变,缺乏灵活性(即“白盒”复用)。
-
组合/聚合复用:耦合度较低,可以灵活地选择成员对象的操作;可以在运行时动态改变。(即“黑盒”复用)
CARP(Composite/Aggregate Reuse Principle:组合/聚合复用原则)
LoD(Law of Demeter:迪米特原则)
-
一个软件实体对其他实体的引用越少越好
-
简单地说,LoD就是指一个软件实体应该尽量少与其他实体发生相互作用。
使用接口的优点
- Client不必知道其使用对象的具体所属类。
- 一个对象可以很容易地被(实现了相同接口的)的另一个对象所替换。
- 对象间的连接不必硬绑定(hardwire)到一个具体类的对象上,因此增加了灵活性。
- 松散藕合(loosens coupling)。
- 增加了重用的可能性。
- 提高了(对象)组合的机率,因为被包含对象可以是任何实现了一个指定接口的类。