设计模式带来的好处
- 提高代码可重用性
- 提高代码可读性
- 提高代码可扩展性
- 提高代码可靠性
- 使程序呈现高内聚,低耦合的特性
- 单一职责原则
- 接口隔离原则
- 依赖倒置原则
- 里氏替换原则
- 开闭原则
- 迪米特法则
- 合成复用原则
1 单一职责原则
对类来说,一个类只负责一项职责。如果一个类A负责两个不同的职责,当其中一个职责需求需要变更时,可能会使另一个职责也发生改变。单一职责原则比较好理解,就不做过多介绍。使用单一职责原则,可以降低类的复杂度,使一个类只负责一项职责,降低需求变更引起的风险。
2 接口隔离原则
客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立再最小的接口上。【设计模式七大原则】什么是一个类的依赖对另一个类的依赖应该建立再最小接口上呢?首先要理解的是,当一个类要依赖另一个类时,一般是通过接口来实现的。如下图:
文章图片
ClassA要依赖ClassB,如ClassA中有一个成员变量为ClassB,那么这个变量的类型到底是ClassB还是Interface呢?应是Interface,即变量名b1。why?为了方便修改和扩展。如果以后ClassB过时了,需要有一个新的类ClassC继承Interface,那么,完全不影响ClassA的内部,只需要将ClassC的实例传给ClassA即可。
接下来就要理解什么是最小接口了,看下面这个图:
文章图片
ClassA通过Interface依赖ClassC,ClassB通过Interface依赖ClassD。
但是,ClassA中只用到了method1,2,3。而ClassB只用到了method1,4,5。这时候就违反了接口隔离原则。应为ClassA依赖了它不需要的接口method4,5。ClassB同理。且ClassC和ClassD要实现不需要的接口。应该改为下图:
文章图片
当然,也可以让Interface2和Interface3都继承Interface1。
3 依赖倒置原则
高层模块不应该依赖低层模块,二者都应该依赖其抽象依赖倒置原则设计理念在于,相对于细节的多变性,抽象的东西要稳定的多。使用抽象的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类完成。下面来举例:
抽象不应该依赖细节,细节应该依赖抽象
中心思想是面向接口编程
有一个Person对象,需要接受电子邮件的消息:
文章图片
Person类的receive方法中调用Email的getInfo方法获取。但是,如果还有接收微信、QQ的消息呢,以后还要扩展其他的方式呢?这时就不得不修改Person类的代码。如果采用下图实现,就不会遇到这种问题:
文章图片
这是,如果以后要扩展其他方式,只需要增加一个类继承IReceiver即可,不需要修改Person类。
4 里氏替换原则
如果对于类型为T1的对象o1,都有类型为T2的对象o2,使得T1定义的所有程序P在所有的对象o1都换成o2时,程序P的行为没有发生变化,那么类型T2是T1的子类型。要准许里氏替换原则,就是在子类中尽量不要重写父类的方法。
换句话说,就是所有引用基类的地方必须能透明的使用子类对象,更通俗的说,所有使用基类的地方都必须能用子类代替。
继承在给程序带来便利的同时,也带来了弊端。继承包含这样一层含义,父类中凡是已经实现好的方法,实际上是在设定规范和契约,虽然它不强制要求所有的子类必须遵循这些契约,但如果子类对这些已经实现的方法随意修改,就会对继承体系造成破坏。里氏替换原则告诉我们,在适当的情况下,可以通过聚合、组合、依赖来解决问题。
如果说无法避免,可以考虑再往上抽象出一个更加基础的类。
5 开闭原则
一个软件实体如类,模块和函数,应该对扩展开放,对修改关闭。当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改以后的代码来实现变化。
如在依赖倒置原则中举的例子,当需要增加一种接受信息的方式时,可以扩展一个类继承IReceiver类,而不用修改原有的代码,也不会影响客户端的代码。
6 迪米特法则
一个对象应该对其他对象保持最少的了解,即最少知道原则。所谓最少知道原则,即一个类对自己依赖的类知道的越少越好。也就是说,不管别依赖的类多么复杂,都尽量将逻辑封装在类的内部。迪米特法则的核心是降低类之间的耦合。
7 聚合/组合复用原则
尽量使用聚合/组合的方法,而不是继承在里氏替换原则中提到过,在适当的时候,可以通过组合或聚合的方式来解决问题。所谓组合/聚合,就是一个类中保存了另一个类的引用,如ClassA中有一个类型为ClassB的成员变量,ClassA就采用了组合/聚合的方式。组合与聚合的区别在于,组合代表两者间的关系更为紧密,比如汽车与车轮的关系,没有车轮,不可缺少。而聚合代表两者间的关系较弱,比如树木与森林的关系,缺少一棵树,但不会影响森林的存在。
总结
- 找出应用可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起
- 针对接口编程,而不是准对实现编程
- 为了交互对象之间的松耦合而努力
推荐阅读
- 面试|我经历的IT公司面试及离职感受(转)
- java|设计模式——创建型——工厂方法(Factory Method)
- 设计模式|设计模式_创建型模式——工厂方法
- 设计模式|设计模式——创建型软件设计模式——工厂方法模式
- 设计模式之装饰器模式
- 设计模式之设计原则
- 设计模式六大原则(5)(迪米特法则 最少知道)
- 观察者模式实现之EventBus(Google)
- Java高级面试|常见设计模式——装饰模式
- java设计模式——单例模式