设计原则
设计原则
设计模式中的设计原则
封装变化
找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
或者说是:把变化的部分取出来并封装起来,以便以后可以轻易地改动或扩充此部分,而不影响不需要变化的其他部分。
优势:
代码变化引起的不经意后果变少,系统变得更有弹性
针对接口编程
针对接口编程,而不是针对实现编程
将行为放在不同的类中,此类专门提供某行为接口的实现。
针对接口编程的真正意思是:针对超类型编程
利用多态,程序可以针对超类型编程,执行时会根据实际状况执行到真正的行为,不会被绑死在超类型的行为上。
针对接口编程具体的做法:变量的声明类型应该是超类型,然后在运行时才确定。
比如:
Animal animal = new Dog();
另外有个概念叫 依赖于实现:
行为来自超类的具体实现,或是继承某个接口并由子类自行实现而来。
依赖于实现的 缺点:被实现绑的死死的,难于修改行为。
所以不推荐依赖于实现编程。
多用组合,少用继承
优势:
- 弹性大
- 可以在运行时动态改变行为
松耦合
解耦(decouple)
优势:
当两个对象之间松耦合,它们依然可以交互,但是不太清楚彼此的细节。
松耦合的设计之所以能让我们建立 有弹性的OO系统,能够应对变化,是因为 对象之间的相互依赖降到了最低。
为了交互对象之间的松耦合设计而努力!!
开放关闭原则
类应该 对扩展开放,对修改关闭。
目标:
允许类容易扩展,在不修改现有代码的情况下,就可搭配新的行为。
好处:
具有弹性可以应对改变,可以接受新的功能来应对改变的需求。
依赖倒置原则
要依赖抽象,不要依赖具体类。
高层以及低层模块都要依赖于抽象。
(A使用B,A就是高层 B就是低层)
指导方针:
- 变量不可以持有具体类的引用。(使用new就会持有,用工厂避开)
- 不要让类派生自具体类。(如果不这么做,那就依赖具体类了)
- 不要覆盖基类中已实现的方法。(说明不是个好基类)
依赖原则教导我们 尽量避免使用具体类,更加注重如何在设计中避免依赖。
最少知识原则(Least Knowledge)
只和你的密友谈话
当设计一个系统,不管任何对象,都需要注意它所交互的类有哪些,并注意它和这些类是如何交互的。
该原则需要我们在设计中,不要让太多的类耦合在一起,免得修改系统中一部分,会影响到气他部分。 如果许多类之间相互依赖,那么这个系统会变成一个易碎的系统,它需要花许多成本维护,也会因为太复杂而不容易被其他人了解。
指导方针:就任何对象而言,在该对象的方法内,我们只应该调用属于以下范围的方法:
- 该对象本身
- 被当做方法的参数而传递进来的对象
- 此方法所创建或实例化的任何对象
- 对象的任何组件(成员变量)
NOTE:另外有个原则叫 Law of Demeter
跟该原则意思相同,但是该原则的称呼更为恰当。
最少知识原则的缺点:会出现更多的『包装』,可能会导致 复杂度和开发时间的增加,并降低运行时的性能。
好莱坞原则
别调用(打电话给)我们,我们会调用(打电话给)你。
好莱坞原则 可以给我们一种防止『依赖腐败』的方法。
当高层组件依赖地层组件,而地层组件又依赖高层组件,而高层组件又依赖边侧组件,而边侧组件又依然低层组件时,依赖腐败就发生了。(好恐怖- -)
NOTE:要尽量做到避免环状依赖。
在该原则的指导下,我们允许低层组件将自己挂钩到系统上,但是高层组件会决定什么时候和怎么样使用这些低层组件。(换句话说就是,高层对待低层组件的方式是『别调用我们,我们会调用你』)
NOTE:当然,并不是绝对的不能调用。
实际应用于:
工厂方法,观察者,模板方法等模式
单一职责
一个类应该只有一个引起变化的原因
告诉我们:尽量让每个类保持单一责任。
内聚(cohesion
),用来度量一个类或模块紧密地达到单一目的或责任。
当一个模块或一个类被设计成只支持一组相关的功能时,我们说它具有高内聚;反之,当被设计成支持一组不相关的功能时,我们说它具有低内聚。
遵守这个原则容易具有高的凝聚力,更容易维护。
难点:区分责任。