六大设计原则------单一职责原则
单一职责原则
单一职责原则 Single Responsibility Principle 简称SRP
什么是类的单一职责原则:
There should never be more than one reason for a class to change
(应该有且仅有一个原因引起类的变更)
例子:
通常企业级项目都会设计到权限控制模块,而权限控制模块又会涉及到用户、权限、角色这三个部分。
而针对这三个部分,基本上使用的是RBAC模型(Role-Based Access Control),也就是基于角色的访问控制。
通过分配和取消角色来控制用户的权限,使用户和权限分离。
那么针对用户模块,我们需要对用户进行管理、修改用户信息、增加角色、修改角色等操作,那么我们先来看把上述这些操作都写在同一个接口(类)中,是什么情况。
用户信息维护类图:
上述类图设计不合理的地方:
用户的属性和用户的行为没有分开。
理由:
用户的属性和行为都能够改变User类,违背了单一职责原则。
改进方案:
把用户的信息抽取成一个BO(Business Object,业务对象),把用户的行为抽取成一个Biz(Business Logic,业务逻辑)。
职责划分后的类图:
示例代码:
User user = new UserImpl();
UserBo userBo = (UserBo)user;
//赋值
userBo.setPassword(“abc”);
//行为
UserBiz userBiz = (UserBiz)new UserBiz();
userBiz.deleteUser();
在实际运用上,我们更倾向于使用两个不同的类和接口:
项目中经常采用的SRP类图
第二个例子:
模拟电话通话的业务:
电话通话的时候有4个动作发生: 拨号、通话、回应、挂机
那么根据这些动作,我们写一个电话接口:
Public interface Phone {
//拨通电话
public void dial(String phoneNumber);
//通话
public void chat(Object o);
//通话完毕,挂电话
public void hangup();
}
通常情况下,我们都会这么设计接口,但是这个接口有缺陷:
这个接口负责了两个职责:
1、协议管理(拨通电话、挂电话)
2、数据传送(通话)
所以,会有两个原因导致这个接口或实现类影响变化,一个是协议管理的变化,一个是数据传送的变化(因为上网也会传送数据),所以这个接口违背了单一职责原则。
处理:拆分成两个接口
上述这个类图,完全满足了单一职责原则的要求,每个接口职责分明,结构清晰.
但是也有缺陷:
一个手机类(Phone)要把ConnectionManager和DataTransfer组合在一块才能使用。而组合是一种强耦合关系,你和我有共同的生命周期,这样的强耦合关系还不如使用接口实现的方式,而且还增加了类的复杂性,多了两个类。
再次修改类图:
分析一下这个类图:
1、一个类实现了两个接口,把两个职责融合在一个类中。这样做虽然Phone有两个原因引起变化,但是我们是面向接口编程,我们对外公布的是接口而不是实现类。
总结:
单一职责原则的好处:
1、类的复杂性降低,实现什么职责都有清晰明确的定义
2、可读性提高,复杂性降低
3、可维护性提高,可读性提高
4、变更引起的风险降低
单一职责适用于接口、类,同时也适用于方法,也就是说,一个方法尽可能做一件事情。
但是单一职责原则很难在项目中得到体现,因为在项目中需要考虑环境,考虑工作量,考虑人员的技术水平,考虑硬件的资源情况,等等。最终的结果往往违背单一职责原则。所以,在项目中,我们要尽量做到单一职责原则。
上一篇: “最少知识”原则
下一篇: python 文件操作api