设计模式六大原则解读——什么是单一职责
author:陈镇坤27
创建日期:2021年9月X日
文章目录
——————————————————————————————
一、单一职责(Single Responsibility Principle)
1、单一职责的定义
There should never be more than one reason for a class to change.
应该永远最多只有一个动因能够使得类(功能)发生变化。——jkun翻译
首先,类要只专注于某个功能块;其次,当发生出现新的变化时,这类变化应该集中于一类。
这是单一职责的两个特点。
功能块——抽象的功能概念,例如协议管理、数据通讯等
新的变化——功能升级,例如电报到电话的通讯手段的变化
以用户信息管理为例:
第一次抽象概念为用户信息管理接口(大多数实际开发到此即可),然后其中实现设置密码、设置头像、更改姓名、设置用户职位、设置用户部门、删除用户等功能。
第二次抽象概念为将用户信息管理接口再抽象出业务对象操作和业务逻辑操作,将其中的职位、部门、删除操作分离出来。
如下类图为第二次抽象后的结果:
当然,我们更多时候会选择用两个实现类的形式来进行处理
到这里,我们的抽象职责的粒度,是:业务对象和业务逻辑
从职责的主体承载者——接口的角度看,因抽象职责的粒度的不同,其划分还可以更“细节”化。
例如,在一个拨打电话的接口中,仅有以下三个方法。
从抽象职责的粒度为业务需求的角度看,这里已然遵循单一职责。
但其实,从功能内容仍然可继续细分,从中抽象出协议管理和数据通讯。
拨打电话和挂电话便是协议管理;
通话便是数据通讯;
两者的功能相互不影响,但却于接口而言存在两种变化——协议管理的更迭和数据通讯的升级,所以此时,它又没有遵循单一职责了。
怎么改造呢,从面向接口编程的角度分析:
数据通讯以协议管理为前提,所以在通讯的接口中依赖协议管理的接口,然后最终由Phone来实现这两个接口,在暴露调用时,由调用者决定采用哪个接口接收Phone(这是多态的思想)。
如果要保持类也遵循单一职责的原则,则应该是:
在Phone类中声明两个对象的实例(组合),这两个对象分别实现了协议管理和数据通讯的接口。
但该图例中,两个对象与Phone是组合关系,此外还增加了类的复杂性,并不建议如此作为。
2、单一职责的目的
1、类复杂性降低;2、代码可维护性提高——(可读性提高、变更风险性降低);
但是
引用原文的一句话
注意 单一职责原则提出了一个编写程序的标准,用“职责”或“变化原因”来衡量接口或类设计得是否优良,但是“职责”和“变化原因”都是不可度量的,因项目而异,因环境而异。
3、在方法上的单一职责
相比较接口、类的单一职责边界定义的动态变化特性,方法的单一职责判定便显得简单得多,我的理解是:
当方法的指代不清晰、掺杂其他与主体不相干功能时,则违背了其方法的单一职责。
比如当一个方法既可以修改密码,又可以修改家庭地址时,便违背了单一职责。
4、建议
面向接口编程,在拆分上,接口的拆分粒度可以适当缩小,一方面考虑更新迭代的可维护性,一方面也要考虑类的复杂性。最重要的是考虑时间成本。不要盲从学究。
特别强调:方法需要严肃地遵循单一职责。
4、总结
类的单一职责sometimes hard to see,but至少在接口的层面、方法的层面做到单一职责。