天天看點

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);
    }
           

根據實際情況來,如果不公布通信接口和異常判斷,可以寫在一起。

建議是接口一定要做到單一職責,類的設計盡量做到隻有一個條件引起變化,這個條件在一個接口裡面二種不同的實作規則互相引起變化

來自設計模式之禅