一、单一职责原则定义
单一职责原则定义:一个对象应该只包含单一的职责,并且该职责被完整地封装在一个类中。
另外一种定义:就一个类而言,应该仅有一个引起它变化的原因。
二、单一职责原则分析
(1)一个类(或者大到模块,小到方法)承担的职责越多,它被复用的可能性越小,而且如果一个类承担的职责过多,就相当于将这些职责耦合在一起,当其中一个职责变化时,可能会影响其他职责的运作。
(2)类的职责主要包括两个方面:数据职责和行为职责,数据职责通过其属性来体现,而行为职责通过其方法来体现。
(3)单一职责原则是实现高内聚、低耦合的指导方针,在很多代码重构手法中都能找到它的存在,它是最简单但又最难运用的原则,需要设计人员发现类的不同职责并将其分离,而发现类的多重职责需要设计人员具有较强的分析设计能力和相关重构经验。
三、示例
1.分析现有功能
(1)init() 的作用是在登录时,对登录界面进行初始化
(2)display() 负责显示登录界面
(3)validate() 对当前界面用户输入的信息进行语法合法性检验,这个是语法验证,比如说用户的密码输入了没有,是否为空;年龄是否是负数…而不是对用户进行合法性验证
(4)getConnection() ,findUser() ,用户的信息保存在数据库中,要进行用户信息的验证,要连接数据库,并且在数据库中寻找输入的用户。
(5)mian() ,是整个系统的入口
2.存在问题
根据单一职责原则,一个应该只有一个职责。现在的登录类大体来讲至少有3种职责。
(1)前面三个方法是合理的,都是与登录界面有关系的。初始化登录界面,展示登录界面,对界面输入的信息进行语法性检验。
(2)但是 getConnection() 和 findUser() 这两个方法是与业务逻辑有关系的,他们是用来判断一个用户是否是合法的。
(3)mian() 方法与登录类没有关系,它是整个系统的入口。只不过是恰好存在系统入口是先进入登录界面的情况
单一职责另外一种定义:就一个类而言,应该仅有一个引起它变化的原因。从这个角度出发,登录类承担的职责过多,有多个引起它发生变化的原因。
比如说,界面发生变化,要修改 display() ;数据库里面的用户发生变化要修改 getConnection();如果入口要增加一些触发工作,要修改 main()…
四、使用单一职责原则进行重构
使用这个原则的方法就是进行拆分,把一个登录类拆分为四个类,如下图
(1)MainClass: 里有一个 main(),负责系统的入口
(2)LoginForm :是一个界面视图,界面表单。里面有界面的初始化,界面展示,语法检验方法。
(3)UserDAO:是数据访问对象,是用于访问用户对象的,与用户对象打交道的,里面有 findUser()
(4)DBUtil:数据库连接工具,负责与 数据库进行连接
拆分了之后,有变化就修改对应的类就可以。
五、练习
现在设计了一个员工类,如下图:
(1)calculatePay() :计算员工工资
(2)calculateTaxes() :计算税费
(3)WriteToDisk() : 写入员工信息
(4)readFromDisk() :读出员工信息
(5)createXML() 和 parseXML() :将员工数据的格式转换为 XML ,然后使用的时候解析 XML
(6)3 个 …Report() :与报表有关系的
1.存在问题
与前面的例子的问题是一样的,一个类承担多个职责(多个变化点)。
2.进行拆分重构
将一个员工类拆分成6个类,如下图:
(1)Employee类:6个类里面的核心,有两个方法,计算员工的工资和税费。其他的类都是在 Employee 类的基础上面进行扩展,提供一些额外的工具类等
(2)其他的类有箭头指向 Employee 类,表示其他的类里面有一个属性是 Employee 类型的(也就是类属性里面包含 Employee对象)