設計模式——外觀模式
外觀模式(Facade Pattern):隱藏系統的複雜性,並向客戶端提供了一個可以訪問系統的介面。這種型別的設計屬於結構型模式,它向現有的系統新增一個介面,來隱藏系統的複雜性。這種模式涉及到一個單一的類,該類提供了客戶端請求的簡化方法和對現有系統方法的委託呼叫。現實生活中,常常存在很多複雜的例子,例如:去醫院看病,可能要去掛號、門診、化驗、開藥、取藥,讓患者家屬覺得很複雜,如果有提供接待人員,只讓接待人員來處理,就很方便。或者 Java 的三層開發模式等等。軟體設計也是如此,當一個系統的功能越來越強,子系統會越來越多,客戶對系統的訪問也變得越來越複雜。這是如果系統內部發生改變,客戶端也要改變,違背了 “開閉原則” 和 “迪米特法則” 所以有必要為多個子系統提供一個統一的介面,從而降低系統的耦合度,這就是外觀模式。
一、 外觀模式的優點與缺點
外觀模式是 “迪米特法則” 的典型應用,優點如下:
1)、降低了子系統與客戶端之間的耦合度,使得子系統的變化不會影響呼叫它的客戶類,便於子系統內部維護和擴充套件。
2)、對客戶遮蔽了子系統元件,減少了客戶處理的物件數目,並使得子系統使用起來更加容易,降低了複雜性。
3)、降低了大型軟體系統中的編譯依賴性,簡化了系統在不同平臺之間的移植過程,因此編譯一個子系統不會影響其他子系統,也不會影響外觀物件。
4)、子系統也不會影響外觀系統。
5)、通過合理的使用外觀系統,可以更好的幫我們劃分訪問層次,當系統需要層次設計時,可以考慮外觀模式。
6)、在維護一個遺留的大型系統時,可能這個系統已經變得非常難以維護和擴充套件,此時可以考慮為新系統開發一個Facad類,來提供遺留系統的比較清晰簡單的介面,讓新系統與Facade類互動,提高複用性
7)、不能過多的或者不合理的使用外觀模式,使用外觀模式好,還是直接呼叫模組好。要以讓系統有層次,利於維護為目的。
外觀模式的主要缺點如下:
1)、不能很好地限制客戶端使用子類系統。
2)、增加了新的子類系統可能需要修改外觀類。
二、外觀模式結構類圖
外觀(Facade)模式的結構比較簡單,主要是定義了一個高層介面。它包含了對各個子系統的引用,客戶端可以通過訪問外觀類來訪問各個子系統的功能。
外觀模式主要包含一下三種角色:
【1】、外觀(Facade)角色:為多個子系統對外提供一個共同的介面。
【2】、子系統(Sub System)角色:實現系統的部分功能,客戶可以通過外觀角色訪問它。
【3】、客戶(Client)角色:通過一個外觀系統訪問各個子系統。
三、程式碼案例分析
【1】定義 CPU 、Hard、Memory 三大子系統之一:
1 public class Memory { 2 private static Memory memory = new Memory(); 3 public static Memory getInstance() { 4 return memory; 5 } 6 7 public void open() { 8 System.out.println("開啟記憶體"); 9 } 10 11 public void down() { 12 System.out.println("關閉記憶體"); 13 } 14 }
【2】定義外觀類:在構造器中通過呼叫子類的方法,例項化子類物件。
1 public class Facade { 2 private CPU cpu; 3 private Memory memory; 4 private Hard hard; 5 //構造器 初始化子類例項 6 public Facade() { 7 super(); 8 this.cpu = CPU.getInstance(); 9 this.memory = Memory.getInstance(); 10 this.hard = Hard.getInstance(); 11 } 12 13 //封裝所有開啟裝置 14 public void open() { 15 cpu.open(); 16 hard.open(); 17 memory.open(); 18 } 19 //封裝所有關閉裝置 20 public void down() { 21 cpu.down(); 22 hard.down(); 23 memory.down(); 24 } 25 }
【3】客戶端類:通過呼叫外觀類,實現對子類的呼叫
1 public class Client { 2 public static void main(String[] args) { 3 //外觀類 4 Facade facade = new Facade(); 5 //開啟電腦 6 facade.open(); 7 //關閉電腦 8 facade.down(); 9 } 10 }
四、外觀模式應用分析
外觀模式在 MyBatis 框架中應用的原始碼分析:
【1】MyBatis 中的 Configuration 去建立 MetaObject 物件使用到外觀模式
1 public class Configuration { 2 ...... 3 //建立子類例項 4 protected ReflectorFactory reflectorFactory = new DefaultReflectorFactory(); 5 protected ObjectFactory objectFactory = new DefaultObjectFactory(); 6 protected ObjectWrapperFactory objectWrapperFactory = new DefaultObjectWrapperFactory(); 7 8 //封裝複雜的業務邏輯,返回客戶端需要的 MetaObject 9 public MetaObject newMetaObject(Object object) { 10 this.originalObject = object; 11 this.objectFactory = objectFactory; 12 this.objectWrapperFactory = objectWrapperFactory; 13 this.reflectorFactory = reflectorFactory; 14 15 if (object instanceof ObjectWrapper) { 16 this.objectWrapper = (ObjectWrapper) object; 17 } else if (objectWrapperFactory.hasWrapperFor(object)) { 18 this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object); 19 } else if (object instanceof Map) { 20 this.objectWrapper = new MapWrapper(this, (Map) object); 21 } else if (object instanceof Collection) { 22 this.objectWrapper = new CollectionWrapper(this, (Collection) object); 23 } else { 24 this.objectWrapper = new BeanWrapper(this, object); 25 } 26 }
【2】上述外觀模式應用的類圖