本文是《设计模式之禅》、《Head First设计模式》中介绍的单一职责原则的读书笔记和拓展延伸。

参考资料

  1. 《设计模式之禅》
  2. 《Head First设计模式》

Single Responsibility Principle

从它的名字——单一职责就可以知道它的内容:某个主体应该只有一个工作。

There should never be more than one reason for a class to change. 应该有且仅有一个原因引起类的变更。

虽然这个原则的表述很绝对,但实际操作中不能遵守的情况很多,有时候是条件不允许,有时候是应用了后导致了代码不必要的复杂而放弃。

第一个例子的IUserInfo接口的设计介绍了该原则应用的一个简单实践:属性和行为应该分开。User的信息,如名字、电话号码等应该与操作User的行为,如删除、添加角色等分开。分开成两个接口后一个负责用户的属性,一个负责用户的行为。

第二个例子从电话的接口介绍了实际情况中职责的区分。

1
2
3
4
5
6
7
8
public interface IPhone {
//拨通电话
public void dial(String phoneNumber);
//通话
public void chat(Object o);
//通话完毕,挂电话
public void hangup();
}

乍一看不太清楚怎么区分职责,但若了解网络传输的相关知识应该不难想出这里面有两个主要的职责:协议管理数据传输

IPhone这个接口可不是只有一个职责,它包含了两个职责:一个是协议管理,一个是数据传送。dial()和hangup()两个方法实现的是协议管理,分别负责拨号接通和挂机;chat()实现 的是数据的传送,把我们说的话转换成模拟信号或数字信号传递到对方,然后再把对方传递 过来的信号还原成我们听得懂的语言。我们可以这样考虑这个问题,协议接通的变化会引起 这个接口或实现类的变化吗?会的!那数据传送(想想看,电话不仅仅可以通话,还可以上网)的变化会引起这个接口或实现类的变化吗?会的!那就很简单了,这里有两个原因都引起了类的变化。这两个职责会相互影响吗?电话拨号,我只要能接通就成,甭管是电信的还是网通的协议;电话连接后还关心传递的是什么数据吗?通过这样的分析,我们发现类图上 的IPhone接口包含了两个职责,而且这两个职责的变化不相互影响,那就考虑拆分成两个接口.

这种方式采用了组合,但不太好。一个手机类要把 ConnectionManager和DataTransfer组合在一块才能使用。组合是一种强耦合关系,你和我都有共同的生命期,这样的强耦合关系还不如使用接口实现的方式,而且还增加了类的复杂性,多了两个类。

疑问:在这个职责区分中,数据传输接口中方法需要连接管理器接口的参数,是否说明

留言

⬆︎TOP