六大设计原则

  • 单一职责原则
  • 里氏替换原则
  • 依赖倒置原则
  • 接口隔离原则
  • 迪米特法则
  • 开闭原则

1.单一职责原则 (SRP)

1
单一原则要求一个接口或者类只有一个原因引起变化、也就是一个接口或者类只有一个职责

好处:

  • 类的复杂度降低,实现什么职责都有清晰明确的定义
  • 可读性提高
  • 可维护性提高
  • 变更引起的风险降低。变更是必不可少的,如果一个类的单一职责设计得好,那么接口的变更对只对相应的实现类有影响,对其他接口没有影响。对系统的可扩展性、可维护性都有很大的帮助

注意:

单一职责原则提出了一个编写程序的标准,用“职责”或“变化原因”来衡量接口或类设计得是否优良,但是“职责”和“变化原因”都是不可度量的,因项目而异,因环境而异。

2.里氏替换原则

1
2
“所有引用基类的地方必须能透明地使用其子类的对象”
通俗点讲就是:父类出现的地方,子类可以替换父类,并且不会产生任何问题与错误。
  • 子类必须完全实现父类的方法
  • 子类可以有自己的个性
  • 覆盖或者实现父类方法时,输入参数可以被放大
  • 覆写或者实现父类的方法时,输出结果可以缩小

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类声明了复制自身的接口,作为Prototype的子类,ConcretePrototype实现了Concrete复制自身的clone操作。这里的原型通过请求原型clone复制自身,创建一个新对象。

  • 原型使用场景

1、