设计模式基本原则
七大原则
单一职责原则 SRP
Single-Responsibility Principle,就一个类而言,应该仅有一个引起它变化的原因,通俗的说,就是一个类只负责一项职责。此原则的核心就是解耦和增强内聚性。
类的职责主要包括两个方面:数据职责和行为职责,数据职责通过其属性来体现,而行为职责通过其方法来体现。
如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力。这种耦合会导致脆弱的设计,可复用的可能性就越小。
一个类只有一个引起它变化的原因,否则就应当考虑重构,是否重构由引起变化的原因决定,而不由功能决定。虽然职责常常引起变化的轴线,但有时就未必,应该适当考虑;可以通过 Facade 模式或 Proxy 模式进行职责分离。
优点:
降低类的复杂度;
提高类的可读性,提高系统的可维护性;
降低变更引起的风险(降低对其他功能的影响)。
例子:
SpringMVC 中 Entity,DAO,Service,Controller, Util 等的分离。
开闭原则 OCP
Open Close Principle,开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类。
例子:
设计模式中模板方法模式和观察者模式。
里氏代换原则 LSP
Liskov Substitution Principle,所有引用基类 (父类) 的地方必须能透明地使用其子类的对象,即子类能够必须能够替换基类能够从出现的地方,子类也能在基类的基础上新增行为。
LSP 是继承复用的基石,是对“开 - 闭”原则的补充。实现“开 - 闭”原则的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
里氏代换原则是实现开闭原则的重要方式之一,由于使用基类对象的地方都可以使用子类对象,因此在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象。
例子:
正方形是长方形。
接口隔离原则 ISL
(Interface Segregation Principle,ISL): 客户端不应该依赖那些它不需要的接口。(这个法则与迪米特法则是相通的)。
一旦一个接口太大,则需要将它分割成一些更细小的接口,使用该接口的客户端仅需知道与之相关的方法即可。注意,在该定义中的接口指的是所定义的方法。例如外面调用某个类的 public 方法。这个方法对外就是接口。
依赖倒转原则 DIP
Dependency-Inversion Principle 要依赖抽象,而不要依赖具体的实现,具体而言就是高层模块不依赖于底层模块,二者共同依赖于抽象。抽象不依赖于具体,具体依赖于抽象。
实现开闭原则的关键是抽象化,并且从抽象化导出具体化实现,如果说开闭原则是面向对象设计的目标的话,那么依赖倒转原则就是面向对象设计的主要手段。
其他原则 - 合成复用原则
Composite Reuse Principle,合成复用原则就是指在一个新的对象里通过关联关系(包括组合关系和聚合关系)来使用一些已有的对象,使之成为新对象的一部分;新对象通过委派调用已有对象的方法达到复用其已有功能的目的。简言之:要尽量使用组合/聚合关系,少用继承。
其他原则 - 迪米特法则(最少知道原则)
Demeter Principle,为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立,这样,当一个模块修改时,就会尽量少的影响其他的模块,扩展会相对容易,这是对软件实体之间通信的限制,它要求限制软件实体之间通信的宽度和深度。
在迪米特法则中,对于一个对象,其关联的实体包括以下几类:
- 当前对象本身 (this);
- 以参数形式传入到当前对象方法中的对象;
- 当前对象的成员对象(包括集合中的元素);
- 当前对象所创建的对象。
例子:
外观模式 Facade(结构型)
24 大设计模式
学习设计模式
- Java Design patterns
链接:https://java-design-patterns.com/zh/
- Java 全栈知识体系
链接:https://pdai.tech/md/dev-spec/pattern/1_overview.html
- 字节飞扬
链接:https://bytesfly.github.io/blog/#/DesignPattern/overview