前言
鲁迅先生曾经在<<故乡>>中写道"世界上本没有路,走的人多了,也便成了路."这句话同样适用于设计模式当中."世界上本没有设计模式,代码写的多了便总结出了设计模式".使用设计模式是为了可重复使用代码,让代码更容易被他人理解,保证代码的可靠性.通过不断的积累,设计模式也成为了一门重要的课程,精通了设计模式就可以真正的理解软件工程了.要想了解和精通设计模式,首先要知道设计模式当中的六大原则.
下来咱们就逐一罗列一下这六大原则:
一.单一职责原则
定义:
不要存在多于一个导致类变更的原因,一个类只负责一项职责. 尽量使用合成/聚合的方式,而不是使用继承.一个类不额能"太累"了承担的责任越多,它被可服用的可能性就越小.
问题的由来:
类T负责两个不同的职责:职责P1,职责P2.当由于职责P1需求发生改变而需要修改类T是,有可能会导致原本运行正常的职责P2功能发生故障.
解决方案:
遵循单一职责原则.分别建立两个类T1,T2,使T1完成职责P1功能,T2完成职责P2功能.当修改T1类时,P2不会发生故障风险.同理当修改T2时,P1也不会发生故障风险.
二.里氏替换原则
定义:
如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型T是类型S的子类型. 所有引用基类的地方必须能透明的使用其子类对象.
这个定义看起来比较难懂,例如:一个人喜欢动物(S),那这个人一定喜欢苏格兰折耳猫(o1),类型为哺乳动物(T)的一个对象暹罗猫(o2)程序P定义为一个看见猫就高兴的人,苏格兰折耳猫(o1)替换成暹罗猫(o2)后程序P的结果是没有变的这个人依然很高兴.这个时候我们就说哺乳动物类(T)是动物(S)类的子类.
问题由来:
有一个功能P1,由类A完成.现需要将功能P1进行扩展,扩展后的功能为P,其中P由原有功能P1与新功能P2组成.新功能P由类A的子类B来完成,则子类B在完成新功能P2的同时,由可能会导致原有功能P1发生故障.
解决方案:当使用继承时,遵循里氏替换原则.类B继承类A时,除添加新的方法完成新增功能P2外,尽量不要重写父类A的方法,也尽量不要重载父类A的方法.
三.依赖倒置原则
定义:
高层模块不应该依赖底层模块,二者都应该依赖其抽象:抽象不应该依赖细节;细节应该依赖抽象.要针对接口编程,而不是针对现实编程.
问题由来:
类A直接依赖类B,假设要将类A改为依赖类C,则必须通过修改类A的代码来完成.这种情况下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的操作;假如修改类A,会给程序带来不必要的风险.
解决方案:
将类A修改为依赖接口I,类A同接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率.
四.接口隔离原则
定义:
客户端不应该依赖它不与需要的接口;一个类对另一个类的依赖应该建立在最小的接口上.使用个给专门的接口,而不使用单一的总接口.
问题由来:
类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类A和类B来说不是最小接口,则类B和类D必须去实现他们不需要的方法.
解决方案:
将臃肿的接口I拆分为独立的几个接口,类A和类C粉笔与他们需要的接口建立依赖关系.也就是采用接口隔离原则.
五.迪米特法则
定义:
一个对象应该对其他对象保持最少的了解.一个软件实体应当尽可能少的与其他实体发生相互作用.
问题由来:
类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大.
解决方案:
尽量降低类与类之间的耦合.
六.开闭原则
定义:
一个软件实体如类,模块和函数应该对扩展开放,对修改关闭.即软件实体应尽量在不修改原有代码的情况下进行扩展.
问题由来:
在软件按的生命周期内,因为变化,升级和维护等原因需要对软件原有代码进行修改时,可能会给就代码中引入错误,也可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试.
解决方案:
当软件需要变化时,尽量通过扩展软件实体的行为来实现百脑汇,而不是通过修改已有的代码来实现变化.
结尾
设计模式的六大原则是,设计模式的基础.所有的设计模式都围绕这六大原则来应用的.
在上图中,设计1、设计2属于良好的设计,他们对六项原则的遵守程度都在合理的范围内;设计3、设计4设计虽然有些不足,但也基本可以接受;设计5则严重不足,对各项原则都没有很好的遵守;而设计6则遵守过渡了,设计5和设计6都是迫切需要重构的设计。
结尾部分参考博客园中的博客https://www.cnblogs.com/xiaobaizhang/p/7778494.html
其余部分参考资料为JAVA学习手册.如有侵权即删.