设计原则

Posted by 程序亦非猿 on 2016-07-21

设计模式专题系列: 设计模式

持续更新中

设计原则

设计模式中的设计原则

封装变化

找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。

或者说是:把变化的部分取出来并封装起来,以便以后可以轻易地改动或扩充此部分,而不影响不需要变化的其他部分。

优势:

代码变化引起的不经意后果变少,系统变得更有弹性

针对接口编程

针对接口编程,而不是针对实现编程

将行为放在不同的类中,此类专门提供某行为接口的实现。

针对接口编程的真正意思是:针对超类型编程

利用多态,程序可以针对超类型编程,执行时会根据实际状况执行到真正的行为,不会被绑死在超类型的行为上。

针对接口编程具体的做法:变量的声明类型应该是超类型,然后在运行时才确定。

比如:

1
Animal animal = new Dog();

另外有个概念叫 依赖于实现

行为来自超类的具体实现,或是继承某个接口并由子类自行实现而来。
依赖于实现的 缺点:被实现绑的死死的,难于修改行为。

所以不推荐依赖于实现编程。

多用组合,少用继承

优势:

  1. 弹性大
  2. 可以在运行时动态改变行为

松耦合

解耦(decouple)

优势:

当两个对象之间松耦合,它们依然可以交互,但是不太清楚彼此的细节。

松耦合的设计之所以能让我们建立 有弹性的OO系统,能够应对变化,是因为 对象之间的相互依赖降到了最低

为了交互对象之间的松耦合设计而努力!!

开放关闭原则

类应该 对扩展开放,对修改关闭。

目标:

允许类容易扩展,在不修改现有代码的情况下,就可搭配新的行为。

好处:

具有弹性可以应对改变,可以接受新的功能来应对改变的需求。

依赖倒置原则

要依赖抽象,不要依赖具体类

高层以及低层模块都要依赖于抽象。

(A使用B,A就是高层 B就是低层)

指导方针:

  1. 变量不可以持有具体类的引用。(使用new就会持有,用工厂避开)
  2. 不要让类派生自具体类。(如果不这么做,那就依赖具体类了)
  3. 不要覆盖基类中已实现的方法。(说明不是个好基类)

依赖原则教导我们 尽量避免使用具体类,更加注重如何在设计中避免依赖。

最少知识原则(Least Knowledge)

只和你的密友谈话

当设计一个系统,不管任何对象,都需要注意它所交互的类有哪些,并注意它和这些类是如何交互的。
该原则需要我们在设计中,不要让太多的类耦合在一起,免得修改系统中一部分,会影响到气他部分。 如果许多类之间相互依赖,那么这个系统会变成一个易碎的系统,它需要花许多成本维护,也会因为太复杂而不容易被其他人了解。

指导方针:就任何对象而言,在该对象的方法内,我们只应该调用属于以下范围的方法:

  1. 该对象本身
  2. 被当做方法的参数而传递进来的对象
  3. 此方法所创建或实例化的任何对象
  4. 对象的任何组件(成员变量)

方针示意图

NOTE:另外有个原则叫 Law of Demeter 跟该原则意思相同,但是该原则的称呼更为恰当。

最少知识原则的缺点:会出现更多的『包装』,可能会导致 复杂度和开发时间的增加,并降低运行时的性能。

好莱坞原则

别调用(打电话给)我们,我们会调用(打电话给)你。

好莱坞原则 可以给我们一种防止『依赖腐败』的方法。

当高层组件依赖地层组件,而地层组件又依赖高层组件,而高层组件又依赖边侧组件,而边侧组件又依然低层组件时,依赖腐败就发生了。(好恐怖- -)

NOTE:要尽量做到避免环状依赖。

在该原则的指导下,我们允许低层组件将自己挂钩到系统上,但是高层组件会决定什么时候和怎么样使用这些低层组件。(换句话说就是,高层对待低层组件的方式是『别调用我们,我们会调用你』)

NOTE:当然,并不是绝对的不能调用。

实际应用于:
工厂方法,观察者,模板方法等模式

单一职责

一个类应该只有一个引起变化的原因

告诉我们:尽量让每个类保持单一责任。

内聚(cohesion),用来度量一个类或模块紧密地达到单一目的或责任。

当一个模块或一个类被设计成只支持一组相关的功能时,我们说它具有高内聚;反之,当被设计成支持一组不相关的功能时,我们说它具有低内聚。

遵守这个原则容易具有高的凝聚力,更容易维护。

难点:区分责任。