单一职责原则-This is sometimes hard to see

举报
李子捌 发表于 2021/10/15 14:58:35 2021/10/15
【摘要】 单一职责原则(Single Responsibility Principle,简称SRP),指的是不要存在一个以上导致类变更的原因。 There should never be more than one reason for a class to change.

简介

单一职责原则(Single Responsibility Principle,简称SRP),指的是不要存在一个以上导致类变更的原因。

There should never be more than one reason for a class to change.


单一职责原则的优点

  1. 类的复杂性降低,清晰定义类的职责
  2. 可读性提高、复杂性降低
  1. 可维护性高
  2. 有效降低变更的风险;如果一个接口的单一职责做的好,一个接口修改只对响应的实现类有影响,对其他的接口无影响,这样会大大降低变更的风险


单一职责原则使用场景

  1. 模块
  1. 接口、类
  2. 方法



单一职责原则解决实际问题


使用场景

做过项目的人都接触过项目中的人员和资源权限问题,基本上都是采用RBAC模型(Role-Based Acess Control)基于角色的访问控制,通过分配和取消角色来完成用户权限的授予和取消,是的用户(动作主体)和权限(资源的行为)分离。


此时我们需要定义一个用户接口IUserInfo,假如我们将用户管理、修改用户信息、角色管理等信息都封装到这个接口当中。那么此时的接口定义将会如下所示:

public interface IUserInfo {

    /**
     * 用户属性相关
     */
    void setPassword(String password);
    String getPassword();
    void setUserName(String userName);
    String getUserName();
    void setAddress(String address);
    String getAddress();
    
    /**
     * 用户行为相关
     */
    boolean changePassword(String oldPassword, String newPassword);
    boolean deleteUser(String userId);
    boolean addOrg(IUserBo userBo, int orgId);
    boolean addRole(IUserBo userBo, int roleId);
    
}


此时的用户信息维护类图如下所示:

这里有一个非常明显的缺点就是,我们将用户的基本属性处理和用户的行为处理放到了一个接口中维护,这样直接导致将用户的基本属性或者用户的行为发生变更的时候,都会导致我们的IUserInfo接口和UserInfo实现类都会发生改变,这种设计不仅增大了系统的耦合度也给项目维护带来了更高的维护成本,是非常不可取的。


解决办法

我们将IUserInfo接口抽象为两个接口,分别是用户属性相关接口IUserBO,行为相关接口IUserBiz,修改后的代码如下所示:

IUserBO接口定义

/**
 * <p>
 *      用户属性相关(Business Object)
 * </p>
 *
 * @Author: Liziba
 * @Date: 2021/6/20 11:11
 */
public interface IUserBO {

    void setPassword(String password);
    String getPassword();
    void setUserName(String userName);
    String getUserName();
    void setAddress(String address);
    String getAddress();

}

IUserBiz接口定义

/**
 * <p>
 *      用户行为相关
 * </p>
 *
 * @Author: Liziba
 * @Date: 2021/6/20 11:26
 */
public interface IUserBiz {

    boolean changePassword(String oldPassword, String newPassword);
    boolean deleteUser(String userId);
    boolean addOrg(int orgId);
    boolean addRole(int roleId);

}

IUserInfo接口定义

public interface IUserInfo extends IUserBiz, IUserBO{

    /**
     * 用户属性相关
     */
    void setPassword(String password);
    String getPassword();
    void setUserName(String userName);
    String getUserName();
    void setAddress(String address);
    String getAddress();

    /**
     * 用户行为相关
     */
    boolean changePassword(String oldPassword, String newPassword);
    boolean deleteUser(String userId);
    boolean addOrg(int orgId);
    boolean addRole(int roleId);

}


此时的用户信息维护类图如下所示:

此时的UserInfo对象,既可以当做IUserBiz对象,也可以当做IUserBO对象,因为UserInfo分别实现了IUserBiz接口和IUserBO接口。此时的IUserBiz接口和IUserBO接口是满足单一职责原则的,因为他们分别负责的是用户属性相关和用户行为相关的职责,并不相互耦合交叉。



修改前和修改后的调用方式

修改前

IUserInfo userInfo = new UserInfo();
userInfo.setAddress("中国广东深圳");
userInfo.deleteUser("10000000001");

修改后

IUserInfo userInfo = new UserInfo();
IUserBO userBO = (IUserBO)userInfo;
userBO.setAddress("中国广东深圳");

IUserBiz userBiz = (IUserBiz)userInfo;
userBiz.deleteUser("10000000001");


单一职责原则总结

单一职责原则不仅仅适用于接口,对于类、方法乃至包或者模块都应该遵守单一职责原则的设计,如果设计完全不吻合单一职责原则,不仅会给后续开发和维护带来高额成本也非常不利于开发本人对于系统设计和架构思维方式的提升。我们在开发一个项目不仅仅是一个的事情,尽量要往多一步多一版本思考,不能只快乐自己而给他人埋下太多定时炸弹。但是话又说回来,要想做到一个系统或者一个模块中的全部接口、类和方法完全符合单一职责原则,这基本上也是不可能的事情,大多数情况下,单一职责原则的设计会导致接口、类和方法的剧增,此时我们在设计的时候就应该多方面的去考虑了;总之,我们最少要做到一个接口只搞一件事,也就是建议接口一定要做到单一职责原则设计,而其他的也尽量要往这方面靠。


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。