1. 设计模式的目的
使用设计模式是为了解决程序在耦合性,内聚性,可维护性,可扩展性,重用性等方面的问题
- 代码的重用性: 相同功能的代码不用多次编写
- 可读性: 编程规范,便于其他程序员的阅读理解
- 可扩展性: 新增功能十分方便
- 可靠性高: 当我们增加新功能后对原来的功能没有影响
- 使程序呈现高内聚,低耦合的特性
而23中的设计模式有7大设计原则,7大设计原则是设计模式设计出来的依据
2. 设计模式的七大原则
2.1 单一职责原则(Single Responsibility Principle)
每一个类应该专注于做一件事情
- 可以降低类的复杂度,一个类只负责一项职责,其逻辑肯定要比负责多项职责简单的多;
- 提高类的可读性,提高系统的可维护性;
- 变更引起的风险降低,变更是必然的,如果单一职责原则遵守的好,当修改一个功能时,可以显著降低对其他功能的影响。
- 需要说明的一点是单一职责原则不只是面向对象编程思想所特有的,只要是模块化的程序设计,都适用单一职责原则
如果一个类承担的职责过多,就等于把这些职责耦合在一起了。一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力。这种耦合会导致脆弱的设计,当发生变化时,设计会遭受到意想不到的破坏。而如果想要避免这种现象的发生,就要尽可能的遵守单一职责原则。此原则的核心就是解耦和增强内聚性。
代表:迭代器模式
2.2 里氏替换原则(Liskov Substitution Principle)
对于继承来说包含了这样的含义:
父类中凡是已经实现好的方法,实际上是设定规范和契约,虽然他不要求所有的子类必须遵循这些契约,但是如果子类对这些已经实现的方法任意修改,会对整个继承体系造成破坏
同时继承也存在一些弊端,比如使用继承会给程序带来侵入性,程序的可移植性会降低,增肌对象加的耦合性,如果类A被类B继承,那么在类A修改的同时还需要考虑B的变化
为了更好的使用继承,就需要使用里氏替换原则
里氏替换原则说的是在能使用基类的地方也能透明的使用其子类
- 在子类中尽力不要重写父类写好的方法(所谓透明使用)
- 继承让两个类的耦合性增加了,再适当的情况下可以通过聚合,耦合,依赖来解决问题
假如类B继承自类A并且重写了类A的方法fun1(),这样就违背了里氏替换原则,这样整个程序的继承体系的复用性会变差,也就是说之前能用类A使用fun1()的地方现在使用多态替换成子类B运行使用会达不到原先的目的出现错误
里氏代换原则是实现开闭原则的基础,它告诉我们在设计程序的时候进可能使用基类进行对象的定义和引用,在运行时再决定基类的具体子类型
2.3 依赖倒置原则(Dependence Inversion Principle)
实现尽量依赖抽象,不依赖具体实现。
- 高层模块不应该依赖低层模块,二者都应该依赖其抽象
- 抽象不应该依赖细节,详解应该依赖抽象
- 依赖倒置的中心思想是面向接口编程
因为相对于细节的多变性,抽象的东西要更稳定,抽象指定是接口和抽象类,细节指具体的实现类
采用依赖倒置原则可以减少类间的耦合性,提高系统的稳定性,减少并行开发引起的风险,提高代码的可读性和可维护性
简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合
依赖倒置原则的注意事项和细节
- 低层模块尽量都有抽象类或者接口,程序的稳定性更好
- 变量的声明类型尽量使用抽象类或接口,这样我们变量引用和是及对象间就存在一个缓冲层,利于程序的扩展和优化
- 继承时遵循里氏替换原则
从大局看Java的多态就属于这个原则
2.4 接口隔离原则(Interface Segregation Principle)
应当为客户端提供尽可能小的单独的接口,而不是提供大的总的接口,客户端不应该依赖它不需要的接口
暴露行为让后面的实现类知道的越少越好
譬如类ProgramMonkey通过接口CodeInterface依赖类CodeC,类ProgramMaster通过接口CodeInterface依赖类CodeAndroid,如果接口CodeInterface对于类ProgramMonkey和类CodeC来说不是最小接口,则类CodeC和类CodeAndroid必须去实现他们不需要的方法。将臃肿的接口CodeInterface拆分为独立的几个接口,类ProgramMonkey和类ProgramMaster分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则
建立单一接口,不要建立庞大的接口,尽量细化接口,接口中的方法尽量少。也就是要为各个类建立专用的接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。依赖几个专用的接口要比依赖一个综合的接口更灵活。接口是设计时对外部设定的约定,通过分散定义多个接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。
从大局来说Java的接口可以实现多继承就是接口隔离原则的基础保障。
2.5 迪米特法则(Law Of Demeter)
又叫最少知道原则,一个对象应该对其他对象保持最少的了解
-
也就是说对被依赖的类不管有多么复杂,都应该把逻辑封装在类的内部,对外提供public方法,不对外泄漏任何信息,也就是说所有的信息都是通过自己写的public方法暴露给别人的
-
类之和直接朋友通信,我们称出现成员变量、方法参数、方法返回值中的类为直接朋友,也就是直接耦合,而出现在局部变量中的类则不是直接耦合依赖,不是直接耦合依赖的类最好不要作为局部变量的形式出现在类的内部
2.6 开闭原则(Open Close Principle)
面向扩展开放,面向修改关闭。
这是最基础的原则,实际上前面说的都是为了实现这个原则
- 扩展开放指的是对类的提供方是开放的,可以去新增类,也就是所谓的扩展
- 对修改关闭指的是对使用方的修改关闭,不修改使用方的原来代码
2.7 组合/聚合复用原则(Composite/Aggregate Reuse Principle CARP)
尽量使用合成/聚合达到复用,尽量少用继承。
合成/聚合复用原则就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新的对象通过向内部持有的这些对象的委派达到复用已有功能的目的,而不是通过继承来获得已有的功能