設計模式速記-外觀模式
外觀模式
外觀模式定義:
外觀模式是一種通過為多個複雜的子系統提供一個一緻的接口,而使這些子系統更加容易被通路的模式。該模式對外有一個統一接口,外部應用程式不用關心内部子系統的具體的細節,這樣會大大降低應用程式的複雜度,提高了程式的可維護性。
外觀模式的主要應用在于當一個服務系統中有很多接口,而不同的需求需要有不同的調用流程,這時候在這些數量龐大的接口中尋找就不是一件容易的事,是以使用外觀模式将這些接口整合,為某個特定的需求服務,這樣使用者看到的就是這些整合過的接口,目的也更單純一些。為直覺表示有一些外觀模式的例子:
- 公司A與公司B建立了一些業務往來,這時候公司A和公司B都有數量龐大的接口,不可能都提供給對方,那麼就要對每一方的接口需要做整合,将這些接口提煉出來後,再提供暴露給對方。
- 去政府、銀行辦事一般需要很多步驟,而且需要走很多部門辦理流程,而且每個部門需要做的事情不止一個,這時如果按照部門将流程整合,在将這些部門的順序弄好組成一個單獨的辦事部門,這個辦事部門就是一個外觀模式例子。
模式優缺點
優點
- 降低了子系統與用戶端之間的耦合度,使得子系統的變化不會影響調用它的客戶類。
- 對客戶屏蔽了子系統元件,減少了客戶處理的對象數目,并使得子系統使用起來更加容易。
- 降低了大型軟體系統中的編譯依賴性,簡化了系統在不同平台之間的移植過程,因為編譯一個子系統不會影響其他的子系統,也不會影響外觀對象。
缺點
- 不能很好地限制客戶使用子系統類。
- 增加新的子系統可能需要修改外觀類或用戶端的源代碼,違背了“開閉原則”。
示例
1. 示例描述
假如某商城A的登入功能支援商城B的使用者登入,使用者使用商城B的賬戶登入商城A時,商城B就應該提供給商城A一些資料:包括使用者個人資訊、使用者信用狀況、使用者購買過的商品等,并且使用者個人資訊來源于B的使用者管理系統,信用狀況來源于銀行對接系統接口,使用者購買過的商品來源于B的推薦系統。
2. 解決思路
商城B可以使用外觀模式整理公司A需要的接口并暴露給公司A:
- 建立B公司使用者管理系統(UserManagment),提供擷取使用者資訊接口(getUserInfo)
- 建立B公司銀行對接接口(BankManagment),提供擷取信用狀況接口(getCredit)
- 建立B公司推薦系統(RecommentManagement),提供擷取曆史購買記錄接口(listRecord)
- 設計對A提供服務的接口(ACompanyService),包含上述三個提供資訊
- 對接口ACompanyService做執行個體化(ACompanyServiceImpl),持有1、2、3中的系統對象,完成服務提供。
- 測試
3. 示例代碼
- 公司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("啞鈴","發帶","手套"); } }
- 公司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); } }
- 測試代碼
/** * @Description 外觀模式測試 */ public class FacadeTest { @Test public void test(){ ACompanyService service = new ACompanyServiceImpl(); UserInfo userInfo = service.getUserInfo("userid"); System.out.println(userInfo); } }
- 測試結果
userInfo:userid,credit:良好,recordList:[啞鈴, 發帶, 手套]