實例:
當客戶端爲了完成某個功能,需要去調用某個系統中多個模塊時,例如A模塊、B模塊....。那麼對於客戶端而言,就需要知道這些個模塊的功能,還需要知道如何組合這每一個模塊的功能來實現自己想要的功能。它的實現代碼可能是這樣的:
/** * A模塊 */ public interface AModuleApi{ public void testA(); } /** * B模塊 */ public interface BModuleApi{ public void testB(); } public class AModuleImpl implements AModuleApi { @Override public void testA() { System.out.println("A模塊操作"); } } public class BModuleImpl implements BModuleApi{ @Override public void testB() { System.out.println("B模塊操作"); } } /** *客戶端 *@Author: April */ public class Client { public static void main(String[] args) { AModuleApi moduleA=new AModuleImpl(); moduleA.testA(); BModuleApi moduleB=new BModuleImpl(); moduleB.testB(); //.... } }
這對客戶端而言是個麻煩,而且一旦其中某個模塊發生了變化,可能會引起客戶端也要隨之變化。那麼如何實現,才能讓子系統外部的客戶端既能簡單的使用這些子系統內部的模塊功能,而又不用客戶端去與子系統內部的多個模塊交互呢?一個合理的方案就是——外觀模式
定義:爲子系統中一組接口提供一個一致的界面,Facade模式定義了一個高層接口,這個接口使得這一系統更加容易使用
結構示意圖:
其實很簡單,只添加一個Facade對象,然後在裏面實現客戶端需要的功能就可以了:
public class Facade { /** * 示例方法:滿足客戶需求的功能 */ public void test(){ //將實現委派給內部多個模塊 AModuleApi moduleA=new AModuleImpl(); moduleA.testA(); BModuleApi moduleB=new BModuleImpl(); moduleB.testB(); //... } } public class Client { public static void main(String[] args) { //使用Facade new Facade().test(); } }
理解外觀模式
-
本質:封裝交互,簡化調用
-
對設計原則的體現:"迪米特原則(最少知識原則)"
-
外觀模式的目的不是給子系統添加新的功能接口(你可以這麼做,但不建議),而是爲了讓外部減少與子系統內多個模塊的交互,鬆散耦合,從而讓外部能更簡單的使用子系統
-
你可能會問,這不就是把原來客戶端的代碼搬到Facade裏了嗎?有什麼變化啊?其實變化就在於:
-
Facade是位於系統這邊的,它就相當於屏蔽了外部客戶端和系統內部模塊的交互。不但方便了客戶端的調用,而且封裝了系統內部的細節功能。Facade與各個模塊的交互過程已經屬於內部實現了。
-
Facade的功能可以被多個客戶端調用,也就是實現了複用。
-
-
外觀提供了缺省的功能實現。外觀對象可以爲用戶提供一個簡單的、缺省的實現,這個實現對大多數用戶已經足夠。但外觀並不限制那些需要更多定製功能的用戶,可以去訪問內部模塊的功能,即有外觀,但是可以不用。
-
缺點:過多或不太合理的Facade容易讓人迷惑。到底是調用Facade好呢還是直接調用模塊好。