天天看點

設計模式速記-外觀模式

設計模式速記-外觀模式

外觀模式

外觀模式定義:

外觀模式是一種通過為多個複雜的子系統提供一個一緻的接口,而使這些子系統更加容易被通路的模式。該模式對外有一個統一接口,外部應用程式不用關心内部子系統的具體的細節,這樣會大大降低應用程式的複雜度,提高了程式的可維護性。

外觀模式的主要應用在于當一個服務系統中有很多接口,而不同的需求需要有不同的調用流程,這時候在這些數量龐大的接口中尋找就不是一件容易的事,是以使用外觀模式将這些接口整合,為某個特定的需求服務,這樣使用者看到的就是這些整合過的接口,目的也更單純一些。為直覺表示有一些外觀模式的例子:

  • 公司A與公司B建立了一些業務往來,這時候公司A和公司B都有數量龐大的接口,不可能都提供給對方,那麼就要對每一方的接口需要做整合,将這些接口提煉出來後,再提供暴露給對方。
  • 去政府、銀行辦事一般需要很多步驟,而且需要走很多部門辦理流程,而且每個部門需要做的事情不止一個,這時如果按照部門将流程整合,在将這些部門的順序弄好組成一個單獨的辦事部門,這個辦事部門就是一個外觀模式例子。

模式優缺點

優點

  • 降低了子系統與用戶端之間的耦合度,使得子系統的變化不會影響調用它的客戶類。
  • 對客戶屏蔽了子系統元件,減少了客戶處理的對象數目,并使得子系統使用起來更加容易。
  • 降低了大型軟體系統中的編譯依賴性,簡化了系統在不同平台之間的移植過程,因為編譯一個子系統不會影響其他的子系統,也不會影響外觀對象。

缺點

  • 不能很好地限制客戶使用子系統類。
  • 增加新的子系統可能需要修改外觀類或用戶端的源代碼,違背了“開閉原則”。

示例

1. 示例描述

假如某商城A的登入功能支援商城B的使用者登入,使用者使用商城B的賬戶登入商城A時,商城B就應該提供給商城A一些資料:包括使用者個人資訊、使用者信用狀況、使用者購買過的商品等,并且使用者個人資訊來源于B的使用者管理系統,信用狀況來源于銀行對接系統接口,使用者購買過的商品來源于B的推薦系統。

2. 解決思路

商城B可以使用外觀模式整理公司A需要的接口并暴露給公司A:

  1. 建立B公司使用者管理系統(UserManagment),提供擷取使用者資訊接口(getUserInfo)
  2. 建立B公司銀行對接接口(BankManagment),提供擷取信用狀況接口(getCredit)
  3. 建立B公司推薦系統(RecommentManagement),提供擷取曆史購買記錄接口(listRecord)
  4. 設計對A提供服務的接口(ACompanyService),包含上述三個提供資訊
  5. 對接口ACompanyService做執行個體化(ACompanyServiceImpl),持有1、2、3中的系統對象,完成服務提供。
  6. 測試

3. 示例代碼

  1. 公司B的三個管理系統
    /**
     * @Description 公司B 使用者管理系統
     */
    public class UserManagement {
    
        /**
         * 擷取使用者資訊
         * @param userId 使用者Id
         * @return 經過調用整合後傳回 使用者資訊
         */
        public String getUserInfo(String userId){
            // 簡單起見直接傳回userId
            return userId;
        }
    }
    /**
     * @Description 公司B 銀行對接系統
     */
    public class BankManagment {
        /**
         * 擷取使用者信用狀況
         *
         * @param userId 使用者ID
         * @return 信用狀況
         */
        public String getCredit(String userId){
            return getUserCreditFromBank(userId);
        }
    
        /**
         * 從銀行擷取使用者的信用狀況
         *
         * @param userId 使用者Id
         * @return 信用狀況
         */
        private String getUserCreditFromBank(String userId){
            return "良好";
        }
    }
    /**
     * @Description 公司B 推薦系統
     */
    public class RecommentManagement {
        /**
         * 擷取使用者購買記錄
         *
         * @param userId 使用者Id
         * @return 購買記錄表
         */
        public List<String> listRecord(String userId){
            return Lists.newArrayList("啞鈴","發帶","手套");
        }
    }
               
  2. 公司B暴露給公司A的接口和接口實作類
    /**
     * @Description 對A公司暴露的服務
     */
    public interface ACompanyService {
        /**
         * 擷取使用者資訊
         *
         * @param userId 使用者Id
         * @return 使用者資訊
         */
        UserInfo getUserInfo(String userId);
    }
    /**
     * @Description A公司服務實體類
     */
    public class ACompanyServiceImpl implements ACompanyService {
    
        private BankManagment bankManagment = new BankManagment();
        private RecommentManagement recommentManagement = new RecommentManagement();
        private UserManagement userManagement = new UserManagement();
    
    
        @Override
        public UserInfo getUserInfo(String userId) {
            String credit = bankManagment.getCredit(userId);
            List<String> recordList = recommentManagement.listRecord(userId);
            String userInfo = userManagement.getUserInfo(userId);
    
            return new UserInfo(userInfo, credit, recordList);
        }
    }
               
  3. 測試代碼
    /**
     * @Description 外觀模式測試
     */
    public class FacadeTest {
    
        @Test
        public void test(){
            ACompanyService service = new ACompanyServiceImpl();
            UserInfo userInfo = service.getUserInfo("userid");
            System.out.println(userInfo);
        }
    }
               
  4. 測試結果
    userInfo:userid,credit:良好,recordList:[啞鈴, 發帶, 手套]