单一职责原则的定义是:应该有且仅有一个原因引起类的变更。
举例一:电话
传统设计:
一个接口类
1.IPhone:dial(),chat(),hangup()
一个实现类
1.Phone
演变思想:
因为dial和hangup实现的是协议管理,而chat实现的是数据传送;协议的接通和数据的传送都会引起这个接口类或实现类的变化;如拨号和挂断方法只管连接和断开,之后是不关心数据的传送;若按传统设计,一个类就包含了两个职责。
符合该原则的设计:
两个接口类
1.IConnectionManager:dial(),hangup()
2.IDataTransfer:DataTransfer(IConnectionManager cm )
一个实现类
1.Phone
演变问题:
问:为什么演变成两个接口类后,却只有一个实现类,而不是给每一个接口都去实现一下,再强耦合成一个Phone类呢?两个接口是满足了单一职责原则,但实现类仍然没满足,实现类仍然会因两个原因而引变化呀?
答:是的。但若分别有两个实现类,组合在一起后再形成Phone类才能使用,那么组合就是强耦合,增加了类的数据和复杂度,而且在面向接口编程中,对外公开的是接口,而不是实现类。
接口一定要做到单一职责,而实现类的设计尽量 做到只有一个原因引起变化。
举例二:用户
传统设计:
一个接口类
1.IUserInfo:setUserId(),getUserId(),setUserName(),getUserName(),changePassword(),addNewUser()
一个实现类
1.UserInfo
演变思想:
用户的属性(userId,userName等)没有和用户的行为分开,这是一个严重的错误,应该把属性抽取成一个BO(业务对像),行为抽取成一个Biz(业务逻辑)。
符合该原则的设计:
两个接口类
1.IUserBO:setUserId(),getUserId(),setUserName(),getUserName()
2.IUserBiz:changePassword(),addNewUser()
一个实现类
1.UserInfo
使用时如:
......
// 要赋值了就认为它是一个纯粹的BO
IUserBO userBO = (IUserBO) userInfo();
userBO.getUserId();
......
// 要执行动作了就认为它是一个逻辑类
IUserBiz userInfo = (IUserBiz) userInfo();
userInfo.addNewUser();
也适用对方法的设计
单一职责适用于接口、类,也同样适用于类里面的方法,即一个方法尽可能做一件事情。
比如修改用户信息,根据传递类型的不同,把可变长度的参数修改到userBO这个对像上,并写入数据库:
boolean changeUserInfo(IUserBO userBO, String... changeOptions);
这个方法的设计不符合该原则,因为方法的职责不清晰,不单一,不要让别人去猜测这个方法是用来处理什么逻辑的。
比如好的设计如:
boolean changeUserName(String newUserName);
boolean changeTel(String newTel);