简述
单一职责原则(Single Responsibility Principle,简称SRP)。
定义:There should never be more than one reason for a class to change.(应该有且仅有一个原因引起类的变更。)
举例
电话通话通常有4个过程:拨号、通话、回应、挂机,其接口为:
代码为:
public interface IPhone {
// 拨通电话
public void dial(String phoneNumber);
// 通话
public void chat(Object o);
// 通话完毕,挂电话
public void hangup();
}
这样写,按道理说是没有问题的,但它没有满足单一职责原则。单一职责原则要求一个接口或类只有一个原因引起变化,也就是一个接口或类只有一个职责,而上面的接口却负责了多个事情。
IPhone这个接口包含了两个职责:协议管理和数据传送。dial()
和 hangup()
实现协议管理,chat()
实现数据传输。而协议管理和数据传输本是完全不相关的两个模块,数据传输不会关心是移动还是联通的协议;而协议也不会关心传递的是什么数据。所以通过这样的分析,我们考虑把IPhone拆分成两个接口,其类图如下:
这样设计后,一个类实现了两个接口,把两个职责融合在一个类中。你会觉得Phone类有两个原因引起了变化,确实,但别忘记了我们是面向接口编程,我们对外公布的是接口而不是实现类。
通过上面的例子,总结下单一职责原则有什么好处:
- 类的复杂性降低,
- 可读性提高,
- 可维护性高,
- 变更引起的风险降低。
你可能会反思,以前的设计是不是有问题了?其实不然。单一职责原则最难的是职责的划分,“职责”没有一个量化的标准。一个类到底该负责哪些职责?这些职责怎么细化?细化后是否都要有个接口或类?这些都要从实际的项目中考虑。
单一职责原则提出了一个编写程序的标准,用“职责”或“变化原因”来衡量接口或类设计得是否优良,但“职责”和“变化原因”都是不可度量的,因项目而异,因环境而异。
总结
这个设计原则明明是类的设计原则,却整篇都在说接口。对于这个问题,其实非常难回答。因为绝大多数情况下,类的设计都违背单一职责原则,如果每个职责都用一个类来实现,那项目的复杂性会非常高。理论上来说,这个原则非常优秀,但在实际项目开发中,需要考虑很多其它因素,比如项目工期、成本、技术人员水平、硬件情况、网络情况等等。
所以建议大家,接口一定要做到单一职责,类的设计尽量做到只有一个原因引起变化。
(本文部分内容摘录自GoF的《设计模式》和秦小波的《设计模式之禅》,如有与某原创博文雷同,纯属巧合。本博客对网上各博客没有抄袭复制之意,如若侵权,请联系我,我会第一时间修改或删除。)