设计模式 - 设计原则
1. 单一职责原则
Single Responsibility Principle,简称SRP.
这个设计原则备受争议, 只要你想和别人争执、 怄气或者是吵架, 这原则是屡试不爽的。 如果你是老大,看到一个接口或类是这样或那样设的,你就问一句: “你设计的类符合SRP原则吗? ”保准对方立马“萎缩”掉, 而且还一脸崇拜地看着你, 心想: “老大确实英明”。
单一职责原则的定义是: 应该有且仅有一个原因引起类的变更。
单一职责原则在实际中很难做到,我们只能尽量满足.
接口一定要做到单一职责, 类的设计尽量做到只有一个原因引起变化。
2. 里氏替换原则
Liskov Substitution Principle, 简称 LSP
- 第一种定义, 也是最正宗的定义: If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T,the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T .(如果对每一个类型为S的对象o1, 都有类型为T的对象o2, 使得以T定义的所有程序P在所有的对象o1都代换成o2时, 程序P的行为没有发生变化, 那么类型S是类型T的子类型。 )
- 第二种定义: Functions that use pointers or references to base classes must be able to useobjects of derived classes without knowing it.(所有引用基类的地方必须能透明地使用其子类的对象。 )
通俗点理解就是:
只要父类能出现的地方子类就可以出现,而且替换为子类也不会产生任何错误或异常,使用者可能根本就不需要知道是父类还是子类。 但是, 反过来就不行了, 有子类出现的地方, 父类未必就能适应。
3. 依赖倒置原则
Dependence Inversion Principle,简称 DIP
High level modules should not depend upon low level modules.Both should depend upon abstractions.Abstractions hould not depend upon details.Details should depend upon abstractions.
翻译过来, 包含三层含义:
- 高层模块不应该依赖低层模块, 两者都应该依赖其抽象;
- 抽象不应该依赖细节;
- 细节应该依赖抽象。
一句话 面向接口编程
用张图来表示就是:要尽量避免左边的情况,而使用右边的.
依赖倒置原则.png
依赖的方式:
- 通过构造传递并保存到成员变量
- 使用setter 方法并保存到成员变量
- 在使用的方法中的传递参数中
依赖倒置原则在小项目中得不到很好的体现,而在大项目则是很好的利器!
4. 接口隔离原则
- Clients should not be forced to depend upon interfaces that they don't use.(客户端不应该依赖它不需要的接口。 )
- The dependency of one class to another one should depend on the smallest possible interface.(类间的依赖关系应该建立在最小的接口上。)
简单来说就是:
建立单一接口, 不要建立臃肿庞大的接口
它跟单一职责原则容易混淆,到底是单一职责原则还是接口隔离原则,区别是他们站的角度不同:
- 单一职责原则:类和接口职责单一,注重的是 职责
- 接口隔离原则:接口的方法尽量少
我们要做是:
根据接口隔离原则拆分接口时, 首先必须满足单一职责原则。
5. 迪米特法则
迪米特法则(Law of Demeter, LoD) 也称为最少知识原则(Least Knowledge Principle, LKP)
定义:一个对象应该对其他对象有最少的了解
理解:
- 对一个类,暴露的public方法越少越好
- 只和朋友交流 (朋友指:成为变量或方法参数,除此之外都不是朋友)(也就是方法中不需要知道其他类了)
6. 开闭原则
这是六个原则中最重要的一个设计原则!如果把其他五个原则比喻为是西安类的话,这个原则就是他们的抽象类!
前五个原则就是指导设计的工具和方法, 而开闭原则才是其精神领袖。
Software entities like classes,modules and functions should be open for extension but closed for modifications.(一个软件实体如类、 模块和函数应该对扩展开放, 对修改关闭。 )
实现开闭原则的方式有很多,比较普遍的是通过扩展一个类的方式(extends),这样可以复写原有的方法又不会对原有的类造成影响!
为什么要开闭原则?
- 通过扩展来添加功能,原有的测试类不需要改变,只需要添加新的测试类
- 粒度越小, 被复用的可能性就越大.缩小逻辑粒度, 直到一个逻辑不可再拆分为止。
- 读懂原有的代码已经很困难了,在原有的基础上在进行修改更不可能了!
- 需要在设计之初考虑到所有可能变化的因素
如何实现开闭原则?
- 使用抽象:抽象是对变化的封装,也是对代码的约束.通过抽象类或接口规划功能,在实现类中尽量不能出现public方法.抽象尽量稳定,不能随意添加或修改.
- 元数据控制模块i行为:元数据可以理解为配置参数,在spring中通过配置xml可以进行IOC的控制,从而不需要修改java代码.
- 制定项目章程:执行约束,开发人员都遵循.
- 封装变化:将变化封装到接口或抽象类中,使用23中设计模式来封装变化.
设计原则只是些原则,我们只能尽量遵循,实现过程中还要具体问题具体分析,一句话「尽量遵循设计原则」