Java描述設計模式(12):外觀模式
- 2019 年 10 月 4 日
- 筆記
一、生活場景
1、場景描述
在移動互聯網沒有普及之前,去飯店吃飯的流程大致如下:選座位,排隊,點菜,結賬。後來移動互聯網普及,通過手機APP就可以操作這些流程,非常的方便快捷:通過手機可以知道某飯店是不是還有空位,到了飯店之後直接入座,然後通過手機點菜,結賬,中間省去了很多繁瑣的流程。
2、程式碼圖解

3、程式碼實現
/** * 外觀模式描述飯店就餐流程 */ public class C01_InScene { public static void main(String[] args) { EatAppFacade eatAppFacade = new EatAppFacade () ; eatAppFacade.dining(); } } // 預定 class Booking { private static Booking booking = new Booking() ; public static Booking getInstance (){ return booking ; } public void bookPlace (){ System.out.println("位置預定..."); } } // 點餐 class TakeOrder { private static TakeOrder takeOrder = new TakeOrder (); public static TakeOrder getInstance (){ return takeOrder ; } public void orderDishes (){ System.out.println("點餐..."); } } // 付款 class Payment { private static Payment payment = new Payment () ; public static Payment getInstance (){ return payment ; } public void payMoney (){ System.out.println("結賬..."); } } // 點餐APP class EatAppFacade { private Booking booking ; private TakeOrder takeOrder ; private Payment payment ; public EatAppFacade (){ this.booking = Booking.getInstance() ; this.takeOrder = TakeOrder.getInstance() ; this.payment = Payment.getInstance() ; } // 就餐流程 public void dining (){ booking.bookPlace(); takeOrder.orderDishes(); payment.payMoney(); } }
二、外觀設計模式
1、基本簡介
外觀模式是對象的結構模式,客戶端與一個子系統的通訊必須通過一個統一的外觀對象進行。外觀模式提供一個高層次的介面,使得子系統更易於使用。
2、模式圖解

3、核心角色
- 外觀角色
客戶端可以調用這個角色的方法。此角色具有相關的子模組的功能。在正常情況下,本角色會將所有從客戶端發來的請求委派到相應的子系統去。
- 子模組角色
可以同時有一個或者多個子模組。每個子模組都不是一個單獨的類,而是一個類的集合(如上面的子模組就是由ModuleA、ModuleB、ModuleC三個類組合而成)。每個子系統都可以被客戶端直接調用,或者被外觀角色調用。子模組並不知道外觀的存在,對於子模組而言,外觀角色僅僅是另外一個客戶端。
- 客戶端角色
外觀對象功能的調用者。
4、源程式碼實現
public class C02_Facade { public static void main(String[] args) { Facade facade = new Facade(); facade.clientNeed1(); facade.clientNeed2(); } } class ModuleA { public void testA (){ System.out.println("ModuleA.testA()"); } } class ModuleB { public void testB (){ System.out.println("ModuleB.testB()"); } } class ModuleC { public void testC (){ System.out.println("ModuleC.testC()"); } } class Facade { /** * 客戶需求1 */ public void clientNeed1 (){ ModuleA moduleA = new ModuleA(); moduleA.testA(); ModuleB moduleB = new ModuleB(); moduleB.testB(); } /** * 客戶需求1 */ public void clientNeed2 (){ ModuleB moduleB = new ModuleB(); moduleB.testB(); ModuleC moduleC = new ModuleC(); moduleC.testC(); } }
三、Mybatis應用場景
1、使用場景
- org.apache.ibatis.session.Configuration
- org.apache.ibatis.reflection.MetaObject
Configuration 創建 MetaObject 的時候。
2、Configuration源碼
public class Configuration { protected ObjectFactory objectFactory; protected ObjectWrapperFactory objectWrapperFactory; public Configuration() { this.objectFactory = new DefaultObjectFactory(); this.objectWrapperFactory = new DefaultObjectWrapperFactory(); } public MetaObject newMetaObject(Object object) { return MetaObject.forObject(object, this.objectFactory, this.objectWrapperFactory); } // ... 省去其他源碼 }
3、MetaObject 源碼
public static MetaObject forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory) { return object == null ? SystemMetaObject.NULL_META_OBJECT : new MetaObject(object, objectFactory, objectWrapperFactory); }
四、優缺點總結
鬆散了客戶端與子模組的耦合關係,使子模組功能的調用更加簡單。通過合理使用Facade,可以更好地劃分訪問的層次。有些方法是對系統外的,有些方法是系統內部使用的,把需要暴露給外部的功能集中到門面中。如果過多的使用外觀模式,會讓子模組功能的維護變的複雜,一個功能方法改變,會牽扯到多個外觀對象的改變。
五、源程式碼地址
GitHub·地址 https://github.com/cicadasmile/model-arithmetic-parent GitEE·地址 https://gitee.com/cicadasmile/model-arithmetic-parent