定义
单一职责原则(Single Responsibility Principle,简称SRP),顾名思义就是只有一个职责的原则。这样定义的话的确比较简单直白,但是“职责”不是一个能够明确界定的东西,容易引起争议。比如说:“我的职责是开发软件。”这没有问题,但是粒度非常粗,要知道开发软件可以细分为构架搭建、功能实现、调试等等部分,而且这些部分还可以继续细分呢。所以上面的定义是有问题的。我们来看看单一职责原则的原始定义:
There should never be more than one reason for a class to chage.(有且只有一个原因引起一个类的变化。)
它回答了两个问题:
- 单一职责是什么?单一职责不是“只有一个职责”,而是“有且只有一个原因引起变化”;
- 谁需要单一职责?定义中只说了类需要单一职责,但在实践中,接口和方法也需要单一职责。
也就是说,我们在设计一个类、接口或者方法的时候,需要保证有且只有一个原因引起它的变化。
单一职责原则降低了类的复杂性,让每个类分工明确,能有效提高代码的可读性和可维护性。更重要的是,单一职责原则能帮你理清思路:当你面对一个复杂的问题无从下手时,尝试从一个一个负责具体和单一功能的类做起吧!
争议性
单一职责原则是非常简单的一个原则,如果你现在就开始在项目中严格遵守这个原则,保证每个类都是“有且只有一个原因引起变化”,那么你很快就会发现你的类的数量大增。这不难理解,因为以前你可能会写一个像瑞士军刀一样的类,但是现在螺丝刀是一个类,剪刀是一个类,指甲钳是一个类...而且你往往还要把它们组合起来使用,最终结果是增加了复杂性。
单一职责原则的本意非常好,它让每个类都只做一件事,减低了类的复杂性。但是如果严格遵守单一职责原则,又会导致类的数目大增,反而增加了整体的复杂性。这就是单一职责原则的争议性。所以在实践中,你很少会看到严格遵守单一职责原则的代码。
最佳实践
对于类来说,如果实在没必要做到“有且只有一个原因引起变化”,那你至少要保证它的职责只有一个,尽管你这个职责的粒度可能有点大。对于接口和方法来说,必须要做到“有且只有一个原因引起变化”。