设计模式
六大设计原则
- 单一职责原则
- 里氏替换原则
- 依赖倒置原则
- 接口隔离原则
- 迪米特法则
- 开闭原则
1.单一职责原则 (SRP)
1 | 单一原则要求一个接口或者类只有一个原因引起变化、也就是一个接口或者类只有一个职责 |
好处:
- 类的复杂度降低,实现什么职责都有清晰明确的定义
- 可读性提高
- 可维护性提高
- 变更引起的风险降低。变更是必不可少的,如果一个类的单一职责设计得好,那么接口的变更对只对相应的实现类有影响,对其他接口没有影响。对系统的可扩展性、可维护性都有很大的帮助
注意:
单一职责原则提出了一个编写程序的标准,用“职责”或“变化原因”来衡量接口或类设计得是否优良,但是“职责”和“变化原因”都是不可度量的,因项目而异,因环境而异。
2.里氏替换原则
1 | “所有引用基类的地方必须能透明地使用其子类的对象” |
- 子类必须完全实现父类的方法
- 子类可以有自己的个性
- 覆盖或者实现父类方法时,输入参数可以被放大
- 覆写或者实现父类的方法时,输出结果可以缩小
3.依赖倒置原则
“High level modules should not depend upon low level modules.Both should depend upon abstractions.Abstractions should not depend upon details.Details should depend upon abstractions.”
1 | 通俗点讲就是要让父类之间的模块有约束,而不应该在比较具体的子类之间进行模块依赖。在顶层进行依赖,不应该用比较底层的模块之间进行依赖。 |
- 高层模块不应该依赖底层模块,两者都应该依赖其抽象
- 抽象不应该依赖细节
- 细节应该依赖抽象
好处:
采用依赖倒置,可以减少类之间的耦合性,提高系统的稳定性,降低并行开发引起的风险,提高代码的可读性,可维护性。
依赖倒置原则的本质就是通过抽象(接口或抽象类)使各个类或模块的实现彼此独立,不互相影响,实现模块间的松耦合,我们怎么在项目中使用这个规则呢?只要遵循以下的几个规则就可以:
每个类尽量都有接口或抽象类,或者抽象类和接口两者都具备
这是依赖倒置的基本要求,接口和抽象类都是属于抽象的,有了抽象才可能依赖倒置。
变量的表面类型尽量是接口或者是抽象类
很多书上说变量的类型一定要是接口或者是抽象类,这个有点绝对化了,比如一个工具类,xxxUtils一般是不需要接口或是抽象类的。还有,如果你要使用类的clone方法,就必须使用实现类,这个是JDK提供的一个规范。
任何类都不应该从具体类派生
尽量不要覆写基类的方法
如果基类是一个抽象类,而且这个方法已经实现了,子类尽量不要覆写。类间依赖的是抽象,覆写了抽象方法,对依赖的稳定性会产生一定的影响。
结合里氏替换原则使用
4.接口隔离原则
客户端不应该依赖它不需要的接口,类间的依赖应该建立在最小接口上。 意思就是建立单一接口,而不是建立臃肿的接口,对接口尽量细化
“这与单一职责原则不是相同的吗?错,接口隔离原则与单一职责的审视角度是不相同的,单一职责要求的是类和接口职责单一,注重的是职责,这是业务逻辑上的划分,而接口隔离原则要求接口的方法尽量少。”
最佳实践
接口隔离原则是对接口的定义,同时也是对类的定义,接口和类尽量使用原子接口或原子类来组装。但是,这个原子该怎么划分是设计模式中的一大难题,在实践中可以根据以下几个规则来衡量:
一个接口只服务于一个子模块或业务逻辑;
通过业务逻辑压缩接口中的public方法,接口时常去回顾,尽量让接口达到“满身筋骨肉”,而不是“肥嘟嘟”的一大堆方法;
已经被污染了的接口,尽量去修改,若变更的风险较大,则采用适配器模式进行转化处理;
了解环境,拒绝盲从。每个项目或产品都有特定的环境因素,别看到大师是这样做的你就照抄。千万别,环境不同,接口拆分的标准就不同。深入了解业务逻辑,最好的接口设计就出自你的手中!
5.迪米特法则
迪米特法则(Law of Demeter,LoD)也称为最少知识原则(Least Knowledge Principle,LKP),虽然名字不同,但描述的是同一个规则:一个对象应该对其他对象有最少的了解。通俗地讲,一个类应该对自己需要耦合或调用的类知道得最少,你(被耦合或调用的类)的内部是如何复杂都和我没关系,那是你的事情,我就知道你提供的这么多public方法,我就调用这么多,其他的我一概不关心。
类只跟朋友类交流,朋友类的定义是这样的:出现在成员变量、方法的输入输出参数中的类称为成员朋友类,而出现在方法体内部的类不属于朋友类
6.开闭原则
软件实体应该对扩展开放,对修改关闭,其含义是说一个软件实体应该通过扩展来实现变化,而不是通过修改已有的代码来实现变化。
设计模式
原型
- 类图:
原型模型是一个非常简单的设计模式。客户端知道Prototype类。在运行时,抽象Prototype类的子类的任何子类都可以被客户端的意愿被复制。因此,无须手工创建就可以制造同一类型的多个实例。Prototype类声明了复制自身的接口,作为Prototype的子类,ConcretePrototype实现了Concrete复制自身的clone操作。这里的原型通过请求原型clone复制自身,创建一个新对象。
- 原型使用场景
1、