单一职责原则
面向对象三大特性之一的 封装 指的就是将单一事物抽象出来组合成一个类,所以我们在设计类的时候每个类中处理的是单一事物而不是某些事物的集合。
设计模式中所谓的 单一职责原则(Single Responsibility Principle - SRP),就是对一个类而言,应该仅有一个引起它变化的原因,其实就是将这个类所承担的职责单一化。如果一个类承担的职责过多,就等于把这些 职责耦合 到了一起,一个职责的变化可能会 削弱或者抑制 这个类完成其他职责的能力。这种耦合会导致设计变得脆弱,当变化发生时,设计会遭受到意想不到的破坏。
定义:
应该有且仅有一个原因引起类的变更,一个类或者模块只负责完成一个职责
解释:不要设计大而全的类,要设计粒度更小,单一功能的类。即假设一个类中既包含了用户的一些操作,又包含了设置的一些操作,那么就需要将这个类拆分成几个更小,功能更单一、粒度更细的类。
单一职责原则的好处:
- 类的复杂性降低,实现什么职责都有清晰明确的定义
- 可读性提高,复杂性降低
- 可维护性提高,可读性提高
- 变更引起的风险降低
使用场景
在软件设计中,要如何用好单一职责原则也是一个难题,因为遵循这一原则最关键的地方在于职责的划分,而职责的划分是根据需求定的,需要设计人员发现类的不同职责并将其分离,再封装到不同的类或模块中。同一个类(接口)的设计,在不同的需求里面,可能职责的划分并不一样。而发现类的多重职责需要设计人员具有较强的分析设计能力和相关重构经验。
示例:
在一个社交媒体产品中,我们使用UserInfo去记录用户的信息,包括如下的属性
Q:UserInfo类有没有遵守单一职责原则?
A1:遵守了,单一职责原则,因为其中包括都是跟用户相关的个人信息的内容。
A2:没遵守,因为没有把地址相关的信息单独拿出来。
正确答案:
根据实际业务选择是否应该拆分。
- 该社交产品的有用户信息只是用来展示的,那么这个类这样设计就没有问题
- 假设后面这个社交产品又添加了电商模块, 那就需要将地址信息提取出来,单独设计一个类
**注意:**单一职责同样也适用于方法。一个方法应该尽可能做好一件事情。如果一个方法处理的事情太多,其颗粒度会变得很粗,不利于重用
总结:
不同的应用场景、不同阶段的需求背景下,对同一个类的职责是否单一的判定,可能都是不一样的,最好的方式就是我们可以先写一个粗粒度的类,满足业务需求。随着业务的发展,如果粗粒度的类越来越庞大,代码越来越多,这个时候,我们就可以将这个粗粒度的类,拆分成几个更细粒度的类。这就是所谓的持续重构
码越来越多,这个时候,我们就可以将这个粗粒度的类,拆分成几个更细粒度的类。这就是所谓的持续重构
软件设计真正要做的事情就是,发现根据需求发现职责,并把这些职责进行分离,添加新的类,给当前类减负,越是这样项目才越容易维护。杜绝万能类或万能函数!!!