设计模式六大原则

概要

  • 单一职责原则:类的职责要单一;
  • 里氏替换原则:不要破坏继承体系;
  • 依赖倒置原则:要面向接口编程;
  • 接口隔离原则:设计接口的时候要精简单一;
  • 迪米特法则:高内聚,低耦合;
  • 开闭原则:要对扩展开放,对修改关闭。

单一职责原则(Single Responsibility Principle)

定义

  • 一个类只负责一项职责,不要存在多于一个导致类变更的原因。

优点

  • 可以降低类的复杂度,一个类只负责一项职责,其逻辑肯定要比负责多项职责简单的多。
  • 提高类的可读性,提高系统的可维护性。
  • 变更引起的风险降低,变更是必然的,如果单一职责原则遵守的好,当修改一个功能时,可以显著降低对其他功能的影响。

说明

理想情况下,我们希望单一原则能够被所有的单元遵守,每个包,类,方法都有单一的职能归属,这在前期需求确定下的设计也都是可以实现的。实际项目中,需求不断增加和变动导致的整体结构的重新设计几乎是不可避免的,当项目代码达到一定量级的时候,很简单的单一原则有时候遵守起来却代价巨大,这时候就需要考虑投入和产出的关系了。当然,最基本要做的就是最开始设计的时候遵循单一原则,并且定期重构代码,这样在需求变动后改动起来会方便很多。

实现

  • 实际开发中,遵守每个包,类,方法都有单一的职能归属的原则。

里氏替换原则(Liskov Substitution Principle)

定义

  • 在使用基类的的地方可以任意使用其子类,能保证子类完美替换基类。
  • 如果在使用A的地方都可以使用B,那么B是A的子类型。

优点

  • 里氏替换原则实际上体现了子类和父类的关系的含义,有助于在开发理清各个类之间的关系,从而做出更好的设计,同时在需求变更时降低系统出错率。
  • 增强程序的健壮性,即使增加了子类,原有的子类还可以继续运行。

说明

如果子类不能完整地实现父类的方法,或者父类的某些方法在子类中已经发生“畸变”,则建议断开父子继承关系 采用依赖、聚合、组合等关系代替继承。

继承包含这样一层含义:父类中凡是已经实现好的方法,实际上是在设定一系列的规范和契约,虽然它不强制要求所有的子类必须遵从这些契约,但是如果子类对这些非抽象方法任意修改,就会对整个继承体系造成破坏。而里氏替换原则就是表达了这一层含义。

实现

  • 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
  • 子类中可以增加自己特有的方法。
  • 当子类的方法重载父类的方法时,方法的形参要比父类方法的输入参数更宽松。
  • 当子类的方法实现父类的抽象方法时,方法的返回值要比父类更严格。

依赖倒置原则(Dependence Inversion Principle)

定义

  • 高层模块不应该依赖底层模块,二者都该依赖其抽象。
  • 抽象不应该依赖细节;细节应该依赖抽象。

优点

  • 依赖倒置使得调用端在开发时无需关注底层支持模块的具体实现,而只需要关注如何调用。
  • 在设计好接口后,调用端和底层支持的具体实现模块可以并行开发,提高效率。
  • TDD开发模式就是依赖倒置原则最成功的应用。

说明

高层模块就是调用端,低层模块就是具体实现类。抽象就是指接口或抽象类。细节就是实现类。

依赖倒置原则的本质就是通过抽象(接口或抽象类)使个各类或模块的实现彼此独立,互不影响,实现模块间的松耦合。

实现

  • 低层模块尽量都要有抽象类或接口,或者两者都有。
  • 变量的声明类型尽量是抽象类或接口。
  • 使用继承时遵循里氏替换原则。

接口隔离原则(Interface Segregation Principle)

定义

  • 类间的依赖关系应该建立在最小的接口上,调用方不应该依赖和实现它不需要的接口。

优点

  • 类的功能更清晰,且减少冗余
  • 接口设计更灵活,易于拓展和修改

实现

  • 建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少。为各个类建立专用的接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。
  • 接口尽量小,但是要有限度。对接口进行细化可以提高程序设计灵活性,但是如果过小,则会造成接口数量过多,使设计复杂化。
  • 为依赖接口的类定制服务。只暴露给调用的类它需要的方法,它不需要的方法则隐藏起来。只有专注地为一个模块提供定制服务,才能建立最小的依赖关系。

迪米特法则(Law of Demeter)

定义

一个类对自己依赖的类知道的越少越好。也就是低耦合,高内聚。

优点

  • 单个模块的职责分明。
  • 利于并行开发,各模块间不互相影响。

说明

无论是面向过程编程还是面向对象编程,只有使各个模块之间的耦合尽量的低,才能提高代码的复用率。

应该明确每个类的职责,不应该把”多余”的任务交给负责其他职责的类。将职责划分清楚后,由不同的模块和类来实现。

实现

  • 明确每个类的职责,实现良好的任务分配。

开放封闭原则(Open Close Principle)

定义

  • 一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
  • 当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。

优点

  • 对扩展开放意味着要编写可扩展的代码,适应需求变化。
  • 对修改关闭的好处是不修改原有代码的逻辑,不容易通过修改代码使原有业务逻辑发生变化。

说明

开放封闭原则是对设计的一个很高的要求,既要可扩展,易扩展,又要对修改封闭,扩展时不影响原有代码和逻辑。这实际上是我们设计的目标。

装饰模式很好地体现了开放封闭原则。

实现

  • 遵循以上5个原则。
  • 充分理解需求,考虑业务逻辑将来可能会发生的变动和拓展。

总结

设计模式的六大原则是在大量的编程实践中总结出来的良好的设计规范,它更偏向于设计建议而不是定死的规则。在设计中,应该结合实际项目考虑遵循这些规范的程度,不要为了设计而设计。

总结一句话就是:所有的设计原则和规范都是以更高效的开发产出为目标的,遵循任何原则和规范之前都最好考虑一下投入产出比,一切为了更高效的开发服务。

参考资料

http://www.jianshu.com/p/807bc228dbc2
http://www.uml.org.cn/sjms/201211023.asp