欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

六大设计原则------单一职责原则

程序员文章站 2022-05-07 22:39:45
...

单一职责原则

单一职责原则 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、变更引起的风险降低


单一职责适用于接口、类,同时也适用于方法,也就是说,一个方法尽可能做一件事情。


但是单一职责原则很难在项目中得到体现,因为在项目中需要考虑环境,考虑工作量,考虑人员的技术水平,考虑硬件的资源情况,等等。最终的结果往往违背单一职责原则。所以,在项目中,我们要尽量做到单一职责原则。

相关标签: 设计