天天看点

Java 单一职责深入理解

用户、机构、角色管理这些模块,基本上使用的都是RBAC模型(Role-Based Access Control,基于角色的访问控制,通过分配和取消角色来完成。用户权限的授予和取消,使动作主体(用户)与资源的行为(权限)分离),确实是一个很好的解决办法。

用户管理、修改用户的信息、增加机构、增加角色,设计在一个接口中,都是用户管理类

接口设计是有问题:用户属性 和 用户行为没有分开

应该把用户信息抽取成一个BO(业务对象)

行为抽取成一个Biz业务逻辑

interface IUserInfo {
        // 设置用户ID
        void setUserID(String userID);
        // 获取用户名
        String getUserID();
        // 设置密码
        void setPassword(String password);
        // 获取密码
        String getPassword();
        // 设置用户名
        void setUserName(String userName);
        // 获取用户名
        String getUserName();
        // 更改密码
        boolean changePassword(String oldPassword);
        // 删除用户
        boolean deleteUser();
        // 有权限访问用户
        void mapUser();
        // 添加权限
        boolean addOrg(int orglD);
        //添加角色
        boolean addRole(int roleID);
    }
           

一个接口拆分成两个接口的动作,就是依赖了单一职责原则

IUserBO的职责就是收集和反馈用户的属性信息

IUserBiz负责用户的行为,完成用户信息的维护和变更

/**
     * 负责用户属性
     */
    interface IUserBO {
        // 设置用户ID
        void setUserID(String userID);
        // 获取用户名
        String getUserID();
        // 设置密码
        void setPassword(String password);
        // 获取密码
        String getPassword();
        // 设置用户名
        void setUserName(String userName);
        // 获取用户名
        String getUserName();
    }
        /**
     * 负责用户行为
     */
    interface IUserBiz {
        // 更改密码
        boolean changePassword(String oldPassword);
        // 删除用户
        boolean deleteUser();
        // 有权限访问用户
        void mapUser();
        // 添加权限
        boolean addOrg(int orglD);
        //添加角色
        boolean addRole(int roleID);
    }
	// 实现
	class UserInfo implements IUserInfo {}
	
	 /**   
	 *  实现关系 + 泛化关系
     *  @param args
     */
    public  void main(String[] args) {
        IUserInfo userInfo = new UserInfo();
        //我要赋值了,我就认为它是一个纯粹的BO
        IUserBO userBO = (IUserBO) userInfo;
        userBO.setPassword("abc");
        //我要执行动作了,我就认为是一个业务逻辑类
        IUserBiz userBiz = (IUserBiz) userInfo;
        userBiz.deleteUser();
    }
           

单一职责原则的定义是:应该有且仅有一个原因引起类的变更,如下一个接口

包含了两个职责:一个是协议管理,一个是数据传送。

dial()和hangup()两个方法实现的是协议管理,分别负责拨号接通和挂机

chat()实现的是数据的传送

dial()和hangup()协议管理会引起这个接口实现类 chat()数据传送的变化

chat()数据传送例如可以qq,微信,上网等,会引起接口实现类的dial()hangup()协议的变化

interface IPhone {
        //拨通电话
        public void dial(String phoneNumber);
        //通话完毕,挂电话
        public void hangup();
        //通话聊天
        public void chat(Object o);
    }
           

二个职责的可能会相互影响,那就考虑二个接口,

把二个职责融合在一个类里面, 面向接口编程,对外公布是是接口 而不是实现类。

interface IConnectionManager {
        //拨通电话
        public void dial(String phoneNumber);

        //通话完毕,挂电话
        public void hangup();
    }

    interface IDataTransfer  {
        //数据传送
        void DataTransfer(IConnectionManager cm);
    }

    /**
     * 
     *  对象依赖关系
     */
    class Phone implements IDataTransfer{

        @Override
        public void DataTransfer(IConnectionManager cm) {
            cm.dial("电话号码");
            cm.hangup();
        }
    }
           

单一职责适用于接口、类,同时也适用于方法

一个方法尽可能做一件事情,比如一个方法修改用户密码,不要把这个方法放到“修改用户信息”方法中

方法职责不清晰,不单一,不要让别人猜测这个方法可能是用来处理什么逻辑

interface  IUserManager {
        /**
         * 更改用户
         * @param userBO  用户属性接口
         * @param changeOptions 修改类型到用户属性接口上,在保存到db
         */
        void changeUser(单一职责.IUserBO userBO, String... changeOptions);
    }
           

修改成如下

interface IUserManager {
        //修改用户名称
        void changeusername(String newUsername);
        // 修改家庭
        void changeHomeAddress(String newHomeAddressvoid);
        // 修改单体电话
        void changeofficete(String telnumber);
    }
           

根据实际情况来,如果不公布通信接口和异常判断,可以写在一起。

建议是接口一定要做到单一职责,类的设计尽量做到只有一个条件引起变化,这个条件在一个接口里面二种不同的实现规则互相引起变化

来自设计模式之禅