众所周知,设计模式的六大模式是很重要的,几乎所有的模式都是在围绕这六大原则进行的:满足某一个原则的情况下不违反其他的原则。下面我们就来总结一下这六大原则到底都是什么。
1、单一职责原则
就一个类而言,应该仅有一个引起它变化的原因。
例如:手机里有很多的职责,它既可以拍照又可以摄像,又可以听歌还可以打电话发短信等。但是如果单独拿出里面的某一个功能,和专业的工具对比(比如手机的照相功能和专用照相机)其结果肯定是专用的照相机效果比较好一点。再比如本书开头的简单工厂模式,客户端有对算法的选择和相应计算方法的调用,这就相当于给这个类赋予了很多的职责,这样很不容易对代码的复用和修改。我们应该把对算法的选择另提出来一个类。
也就是如果一个类承担的职责过多,就等于把这些的职责都耦合在一起,一个职责的变化就有可能引起本类中其他职责的完成。
其实我们设计软件,做的最多的内容就是发现职责并把这些职责互相分离。
2、开放--封闭原则
对软件实体(类、模块、函数等等)应该可以扩展,但是不可以修改。就是对扩展开放,对修改封闭。
比如:以我们的学习为例子,在TGB我们经常会同时做很多的事情,可能兼顾TGB课程学习的同时我们又要准备自学考试和计算机等级考试以及软件工程师的考试。那么我们怎么样才可以把这些事情都做得很好呢?我们这些考试是肯定不能修改的,所以我们只好扩展自己的时间,做好时间管理,这样即使再多的事情也不会变乱。其实这就是对考试学习的修改关闭,而对时间的扩展开放。
在设计软件的时候肯定会有很多的变化,这是不可避免的,但是有了变化我们就可以用构造抽象来隔离一些变化。也就是面对需求,对程序的改动是通过增加新的代码进行的,而不是修改原有的代码。但是也不是所有的抽象都是好的,我们要拒绝不成熟的抽象。最终的目的就是让我们写得软件达到可维护,可扩展,可复用,灵活性好的目的。
备忘录模式用到了此原则
3、依赖倒转原则
高层模块不应该依赖底层模块,两个都应该依赖抽象;抽象不应该依赖细节,细节应该依赖抽象。
比如现在电脑的主板,CPU,内存等东西都是可以用在任何电脑上的,这就是针对接口设计的。如果这些东西都是针对具体的实现来设计的话,这些东西都需要具体品牌的主板的支持,那么如果我们只是需要换CPU的话就不得不连主板都得换。这是非常不方便的。而这里说得“接口”其实就可以理解为软件中的“抽象”。也就是我们要面对接口编程,而不要面对实现编程。
其实建造者模式就应用了依赖倒转原则,适配器模式也有一定的涉及。
4、里氏代换原则
子类型必须能够替换掉它们的父类型。
比如猫是继承于动物类的,它以动物的身份拥有吃、喝、跑、跳等行为。可是如果我们某一天需要牛,狗也具有这些行为,由于他们都是继承动物的,所以我们只要增加实例化牛、狗的代码就可以使他们有这些行为,而不需要修改其他的地方。
正是由于里氏代换原则(子类型的可替换性),才使得开放--封闭成为了可能(使得父类类型的模块在无需修改的情况下就可以扩展)。
5、迪米特原则
如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
其实观察者模式和外观模式和中介者模式都应用到了这个原则。
迪米特原则强调了类之间的松耦合,类之间的耦合越弱,越有利于复用。这样如果其中一个类被修改的话才不会影响到另一个类。
6、合成/聚合复用原则
尽量使用合成/聚合,尽量不要使用类继承。因为有继承必然会增加两个类之间的耦合性,这对软件的试卷是非诚不利的。
.合成就是组合,体现了严格的部分和整体关系,比如鸟和爪子之间就是合成关系。
.聚合就是一种弱的拥有关系,比如书和书架,这两者都是单独存在的。但是书架可以包含书。
使用对象的聚合/合成有利于保持每个类被封装,使类和类继承层次保持较小规模,不至于增长称为难以维护的庞然大物。
桥接模式和状态模式就应用了此原则。
小结:
这六大原则使我们学习设计模式的时候时刻要考虑的问题,在我们不论是编写代码还是设计软件架构都要满足的条件。如果没有六大原则的约束,我们的代码就不算做到了完美,也就谈不上软件易于复用,灵活,易修改,易维护!