单一职责原则的英文名是 Single Responsibility Principle,简称SRP,是针对类和接口而言的,但是大部分时候我们只针对接口,对于类,涉及到各种成本、技术等各方面原因,很难完全符合单一职责原则。
顾名思义,根据名称就很容易明白这个原则的含义,但是该原则也是备受争议的一个原则,为什么呢?就是对于职责的定义,不同角度的人,不同位置的人,不同水平的人,等等,对职责的理解可能都不一样,那么对于什么是类的职责,怎么划分类的职责,每个人的见解都会不一样。
单一职责原则的定义是:应该有且仅有一个原因引起类的变更。SRP的英文原话是:There should never be more than one reason for a class to change.
举一个很简单的例子:员工管理(写过程序的人应该都遇到过吧),员工管理不仅包括员工本身属性的管理(如用户名、密码、地址、年龄等等),还包括其部门、角色、权限等管理,如果把这些功能都放在一个接口中声明,那么接口不仅庞大,而且功能复杂,以后即使需要修改,难免不保证会影响其他接口方法。再回过头来看看单一职责的含义,我们把部门的管理、角色的管理、权限的管理都单独出去出来,对外声明独立的接口,是不是就清晰多了呢?相互的接口完成的功能也清晰明了。
通过这里,我们可以看到单一职责的有点:
1、接口的复杂性降低,声明实现什么样的职责清晰明确,一目了然
2、可读性提高,复杂性降低,职责单一,可读性当然提高了
3、可维护性提高,可读性提高了,维护性就提高了,
好吧,一串废话,都是套路。
上面基本是针对接口的,那么方法呢?其实变通一下,方法也是适合单一职责的,如:我之前写的代码就会有如下情况
修改用户信息 updateUser(User user,int opt) ,通过opt标记位来表示要修改的用户信息,是修改用户名还是密码还是手机号等等,看起来很简洁,但是在实现的类里面,一个方法中包含了多个功能,并且要用户知道opt的含义,所以这种设计是不合理的。在接口声明的地方,修改的信息单独作为一个接口就行,
changeName(String name);changePwd(String pwd);
这样用户看起来一下子就知道该接口的方法的职责,并且在实现类中的这个方法职责是单一的,该修改什么就修改什么,和其他的属性完全不相关,不会相互影响。
对于接口,对于方法,我们再设计的时候一定要做到单一,但是对于实现类就需要多方面考虑了。生搬硬套单一职责原则会引起类的剧增,给给维护带来非常多的麻烦,而且过分的细分类的职责也会增加系统的复杂性。本来一个类可以实现的行为非要拆分到两个类里面,然后在使用聚合或者组合(聚合和组合是类图关系中的术语,这里就不在具体阐述了)的方式耦合在一起,增加了系统的复杂性。
所以对于单一职责,建议是接口和方法一定要单一职责,类的设计尽量做到只有一个原因引起变化。
网友评论