本章内容涉及到面向对象的设计模式中:
- 三个基本特征是:封装、继承、多态;
- 四大特点:可维护、可复用、可扩展、灵活性好;
- 七大设计原则:单一职责原则、开闭原则、里氏代换原则、依赖倒转原则、迪米特法则 、接口隔离原则、合成/聚合复用原则;
设计模式系统 具备的特点()
用活字印刷说明四大特征:
- 第一,只需更改要改之字,此为 可维护 ;
- 第 二,这些字并非用完这次就无用,完全可以在后来的印刷中重复使用,此乃 可复用 ;
- 第三,此诗若要加字,只需另刻字加入即可,这是 可扩展 :
- 第四, 字的排列其实可能是竖排可能是横排,此时只需将活字移动就可做到满足排列需求,此是 灵活性好 。
同时:考虑使用封装、继承 、多态把程序的糯合度降低。
七大设计原则
标记 | 设计模式原则名称 | 简单定义 |
---|---|---|
OCP | 开闭原则 | 对扩展开放,对修改关闭 |
SRP | 单一职责原则 | 一个类只负责一个功能领域中的相应职责 |
LSP | 里氏代换原则 | 所有引用基类的地方必须能透明地使用其子类的对象 |
DIP | 依赖倒转原则 | 依赖于抽象,不能依赖于具体实现 |
LOD | 迪米特法则 | 一个软件实体应当尽可能少的与其他实体发生相互作用 |
ISP | 接口隔离原则 | 类之间的依赖关系应该建立在最小的接口上 |
CARP | 合成/聚合复用原则 | 尽量使用合成/聚合,而不是通过继承达到复用的目的 |
单一职责原则
简称 SRP(The Single Responsibility Principle,),是指就一个类而言,应该仅有一个更改它的原因。也即这个类只有一个职责。
使用动机:
若不遵守单一职责原则,即一个类有一个以上的职责,则当一个职责发生变化时,可能会影响其他职责,从而影响代码的维护。
如何使用:
核心在于职责的分解。需要将相同的职责放到一起,不同的职责分开到不同的类的实现中去。具体来说,对于一个类,如果能想到多于一个的动机去改变一个类,那么该类具有多于一个的职责,应该考虑将类的职责分解。
使用原则:
- 每一个类实现的职责有清晰明确的定义。
- 一个类的修改只对自身有影响,对其他类没有影响。
开闭原则
简称 OCP(The Open-Closed Principle),是指软件实体(类、模块、函数等)应该可以扩展,但是不可以修改。即对于扩展是开放的,对于更改是封闭的。通俗来说就是对于要增加的新功能或要调整的改动,尽量扩展新代码而不是修改已有代码。
使用动机
面对需求改变可以保持相对稳定,使得系统可以在第一个版本以后不断推出新的版本。
如何使用
通过对以下可能时机的变化,创建抽象,隔离以后发生的同类变化。
- 在开发工作展开前预测可能的变化。
- 或展开不久后知道可能发生的变化。
- 或当实际需要发生时带来的变化。
使用原则
- 仅对程序中呈现出频繁变化的部分做出抽象。
- 不要刻意对每个部分进行抽象,拒绝不成熟的抽象,它和抽象本身一样重要。
依赖倒置原则
简称 DIP(Dependence Inversion Principle),是指程序不应该依赖细节,细节应该依赖于抽象。简单来说,就是要针对接口编程,不要针对实现编程。
使用动机:
面对不同的具体实现做到易拔插,松耦合。
如何使用:
- 使用接口或抽象类的目的是制定好规范,不涉及任何具体的操作,把展现细节的任务交给实现类去完成。
- 让程序中的所有依赖关系都终止于抽象类或接口。
使用原则:
- 高层模块不应该依赖低层模块,两个都应该依赖抽象。
- 抽象不应该依赖细节,细节应该依赖抽象。
里氏替换原则
简称 LSP(Liskov Substituion Principle),一个软件实体如果使用的是一个父类的话,一定适用于其子类,而且它察觉不出父类和子类的区别。也就是说,在软件里面,把父类都替换成它的子类,程序的行为没有变化。简单来说,子类型必须能够替换掉它们的父类型。
使用动机 :
父类能够真正复用(继承),子类也能够在父类的基础上增加新的行为。
如何使用
- 父类一般使用抽象类或接口。
- 抽象类定义公共对象和状态;接口定义公共行为。
- 子类通过继承父类和接口进行扩展。
使用原则:
- 子类方法的参数类型必须与父类相匹配或更抽象。
- 子类的返回值类型必须与父类或其子类相匹配。
- 子类方法的异常必须与父类能抛出的异常(或其子类)相匹配。
- 子类不应该加强参数条件限制。
- 子类不能修改父类的私有成员变量。
迪米特原则
简称 LoD(Law of Demeter),也叫最小知识原则。是指如果两个类不必彼此互相通信,那么这两个类就不应当发生直接的相互作用;如果其中一个类需要调用另一个类的某一个方法,可以通过第三者转发这个调用。
使用动机
强调类之间的松耦合。类之间的耦合越弱,越有利于复用和扩展。另外,一个处于弱耦合的类被修改,不会对有关系的类造成波及。
如何使用
- 在类的结构设计上,每一个类都应当尽量降低成员的访问权限,不需要让别的类知道的字段或行为就不要公开。
- 类之间不直接建立联系,通过中间类来中转。
使用原则
- 减少公开方法和变量。
- 每个类对其他类知道的越少越好。
- 类不应该知道它所操作的对象的内部细节。
接口隔离原则
接口隔离原则(Interface Segregation Principle,ISP)的定义是客户端不应该依赖它不需要的接口,类间的依赖关系应该建立在最小的接口上。简单来说就是建立单一的接口,不要建立臃肿庞大的接口。也就是接口尽量细化,同时接口中的方法尽量少。
使用动机
单一职责原则注重的是类和接口的职责单一,这里职责是从业务逻辑上划分的,但是在接口隔离原则要求当一个接口太大时,我们需要将它分割成一些更细小的接口,使用该接口的客户端仅需知道与之相关的方法即可。也就是说,我们在设计接口的时候有可能满足单一职责原则但是不满足接口隔离原则。
如何使用
使用原则
- 使用接口隔离原则前首先需要满足单一职责原则。
- 接口需要高内聚,也就是提高接口、类、模块的处理能力,少对外发布public的方法。
- 定制服务,只提供访问者需要的方法。
- 接口设计是有限度的,接口的设计粒度越小,系统越灵活,但是值得注意不能过小,否则变成"字节码编程"。
合成/聚合复用原则
合成/聚合复用原则
合成/聚合复用原则(Composite/Aggregate Reuse Principle,CARP)一般也叫合成复用原则(Composite Reuse Principle, CRP),定义是:尽量使用合成/聚合,而不是通过继承达到复用的目的。
合成/聚合复用原则就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新的对象通过向内部持有的这些对象的委派达到复用已有功能的目的,而不是通过继承来获得已有的功能。
聚合(Aggregate)的概念
聚合表示一种弱的"拥有"关系,一般表现为松散的整体和部分的关系,其实,所谓整体和部分也可以是完全不相关的。例如A对象持有B对象,B对象并不是A对象的一部分,也就是B对象的生命周期是B对象自身管理,和A对象不相关。
合成(Composite)的概念
合成表示一种强的"拥有"关系,一般表现为严格的整体和部分的关系,部分和整体的生命周期是一样的。
聚合和合成的关系:
参考内容:
Github - 《大话设计模式》解读
腾讯云 - 设计模式概念和七大原则
Github - Datawhale《大话设计模式》解读