动力节点首页 全国咨询热线:400-8080-105

绑定手机号,登录
手机号

验证码

微信登录
手机号登录
手机号

验证码

30天自动登录
微信登录与注册
微信扫码登录与注册

扫码关注微信公众号完成登录与注册
手机号登录
首页 > 文章

设计模式的六大原则

03-29 16:17 356浏览
举报 T字号
  • 大字
  • 中字
  • 小字

1.单一职责原则

什么是“单一职责原则”?

如果要理解为:一个类只有一个职责,当然也是可以的,简单化嘛。

单一职责的原话解释是这样的:There should never be more than one reason for a class to change.

饱受争议的原则

为什么饱受争议呢?看着多单纯一原则啊。

这样,我们来看一个打电话的过程:

class Phone {

    void dial(String phoneNumber);

    void dataTransfer(Object data); 

    void hangup();
}

这个有没有问题?是有那么小问题的嘞。

比如说现在拨号的方法要改一下,我变成拨不通就一直拨,那这个类变一下。

然后我通信的方法再改一下,我现在不允许两个人同时说话,一个说完另一个再说,那这个类再变一下。

这个类,有两个职责:协议管理和数据传送。

那怎么搞?把那俩接口独立出来呗,然后将两个职责融合在一个类中。

现在变成了一个类融合了两个接口,确实那个实现类还是有两个原因引起变化,但是别忘了,我们是面向接口编程(后面会提到,依赖倒置原则)。我们对外公布的是接口,又不是实现类。

如果你非要对这个例子实现单一原则,也可以,你要有那个权力或精力。

“单一职责原则”的优势

  • 类的复杂性降低,实现什么职责都有明确的定义。 这是最首要的,如果不能降低复杂度,那就别分开
  • 可读性提高
  • 可维护性提高
  • 变更引起的风险降低

对于接口,我们在实现的时候一定要做到单一,但是对于实现类就需要多方面考虑了。生搬硬套的话会有什么不良反应,去试试就知道了。单一职责很难在项目中得到体现,就拿上面那例子来说,能把接口分开就谢天谢地吧。

2.里氏替换原则

什么是“里氏替换原则”?

这个原则,说简单也简单,说拗口也拗口。

是这样说的:Function that use pointers or references to base classes must be able to use objects of derived classes without knowing it.

所有引用基类的地方,必须能透明的使用其子类对象。

什么意思呢?就是子类必须实现父类的所有方法。有父类出现的地方,子类就可以出现。

关于里氏替换原则

关于里氏替换原则,我并不想讲太多,无非就是父类弄成纯虚基类,然后客端调用的时候以子类来new出父类声明的对象:父类 * 对象 = new 某子类();

这种格式后面会常见,见到的时候自然就明白了。

3.依赖倒置原则

什么是“依赖倒置原则”

这是我最喜欢的一个原则,也是受益最大的。

它的定义是:High level modules should not depend upon low level modules. Both should depend upon abstractions. Absteactions should not depend upon details.Details should depend upon abstractions.

· 高层模块不应该依赖于低层模块,二者都应该依赖于抽象。

· 抽象不应该依赖于细节。

· 细节应该依赖于抽象。

这类似于我们的电脑,它是松耦合、强内聚的,是怎么组装的呢?像内存条这种东西啊,管你是哪家生产的,只要符合规格,再比如鼠标、键盘、电池(电池得配套),反正哪个部件坏了就换哪个部件。为什么这些部件不论插在哪一台电脑上都能使用呢?是这些部件配合电脑主板设计,还是电脑主板配合这些零部件设计呢?

就拿CPU来说,CPU的对外都是针脚式或触点式的标准接口,只要接口设计好,内部再复杂和外界也没有关系。哪个主板要插CPU,那就得和CPU的接口对上。那么这时候如果电脑的内存条坏了,就不该成为你更换麦克风的理由。

依赖倒置,让项目并驾齐驱

我们来思考一下依赖倒置对并行开发的影响。

如果两个类之间有依赖关系,只要定制出两者之间的接口(或抽象类),就可以独立开发了。就像我最近做的一个图书管理项目,只要合理地运用依赖倒置,便可以很好的将界面与后台数据访问解耦合,从而实现并行开发。

依赖倒置原则的本质就是通过抽象使得各个类或模块的实现彼此独立,不互相影响,实现模块之间的松耦合,我们怎么在项目中使用这个规则呢?只要通过以下的几个规则:

  • 每个类尽量都有接口或抽象类,或者抽象和接口二者都具备。
  • 变量的表面类型尽量是接口或者抽象类
  • 任何类都不应该从具体类派生。
  • 尽量不要覆写基类的方法。
  • 结合里氏替换原则。

4.接口隔离原则

什么是“接口隔离原则”?

它建立在“依赖倒置原则”之上,

它的定义有俩:

· Client 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.

· 类之间的依赖关系应该建立在最小的接口上。

接口要高内聚

什么是高内聚?高内聚就是提高接口、类、模块的处理能力,减少对外的交互。比如说你告诉你的保镖,今天去给我买一打爱马仕,他就去了。你也不用问他花了多少钱,他也不用问你是不是抽风了,这种不问条件执行的行为就是高内聚。

接口是对外的承诺,承诺越少对系统的开发越有利,变更的风险也越大,同时也有利于降低成本。

最佳实践

- 一个接口只服务于一个子模块或业务逻辑
- 通过业务逻辑压缩接口中的public方法,接口要勤快点重构
- 已经被污染的接口,尽量去修改
- 了解环境,拒绝盲从

5.迪米特法则

松耦合的法则:迪米特法则

英文解释:Only talk to your immedate friends.

只与直接的朋友通信。

如果两个类之间不能直接通信,那么这两个类就不应该发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。

迪米特法则首先强调在类的设计上,每一个类都应该尽量降低成员的访问权限,强调了类之间的松耦合。

类之间的耦合越弱,越有利于重复利用,一个处在弱耦合的类被修改,不会对相关类造成波及。

6.开-闭原则

何为“开闭原则”

Software entities like classes, modules and functions should be open for extension but closed for modifications.

一个软件实体,应该对拓展开放,对修改关闭。

抽象实体:

1、项目或软件产品中按照一定的逻辑规则划分的模块。
2、抽象类
3、方法

如何应对需求变化?

既然说,对修改要关闭,那需求变化了怎么办?

有如下方法:

1、修改接口
2、修改实现类
3、通过拓展实现变化

 

0人推荐
共同学习,写下你的评论
0条评论
我是码农
程序员我是码农

25篇文章贡献87343字

相关课程 更多>

作者相关文章更多>

推荐相关文章更多>

Java面试题及答案整理

代码小兵66904-21 20:01

6道经典算法面试题

杨晶珍05-12 16:39

简述Spring MVC的核心组件

代码小兵49806-11 16:26

SpringMVC 中的组件

代码小兵49806-11 16:28

Spring常见面试题

代码小兵92504-17 16:07

发评论

举报

0/150

取消