外觀模式
外觀模式(Facade Pattern)隱藏系統(tǒng)的復雜性,并向客戶端提供了可以訪問系統(tǒng)的接口。這種類型的設計模式屬于結(jié)構(gòu)型模式,它向現(xiàn)有的系統(tǒng)添加一個接口,來隱藏系統(tǒng)的復雜性。
這種模式涉及到一個單一的類,該類提供了客戶端請求的簡化方法和對現(xiàn)有系統(tǒng)類方法的委托調(diào)用。
介紹
意圖:為子系統(tǒng)中的一組接口提供一個一致的界面,外觀模式定義了一個高層接口,這個接口使得這一子系統(tǒng)更加容易使用。
主要解決:降低訪問復雜系統(tǒng)的內(nèi)部子系統(tǒng)時的復雜度,簡化客戶端與之的接口。
何時使用: 1、客戶端不需要知道系統(tǒng)內(nèi)部的復雜聯(lián)系,整個系統(tǒng)只需提供一個"接待員"即可。 2、定義系統(tǒng)的入口。
如何解決:客戶端不與系統(tǒng)耦合,外觀類與系統(tǒng)耦合。
關(guān)鍵代碼:在客戶端和復雜系統(tǒng)之間再加一層,這一層將調(diào)用順序、依賴關(guān)系等處理好。
應用實例: 1、去醫(yī)院看病,可能要去掛號、門診、劃價、取藥,讓患者或患者家屬覺得很復雜,如果有提供接待人員,只讓接待人員來處理,就很方便。 2、JAVA 的三層開發(fā)模式。
優(yōu)點:
- 減少系統(tǒng)相互依賴。
- 提高靈活性。
- 提高了安全性。
缺點:不符合開閉原則,如果要改東西很麻煩,繼承重寫都不合適。
使用場景:
- 為復雜的模塊或子系統(tǒng)提供外界訪問的模塊。
- 子系統(tǒng)相對獨立。
- 預防低水平人員帶來的風險。
注意事項:在層次化結(jié)構(gòu)中,可以使用外觀模式定義系統(tǒng)中每一層的入口。
實現(xiàn)
我們以廚師為例。我們將想要吃的食物告訴廚師,即調(diào)用廚師對象的做菜接口,由廚師做好飯,即廚師屏蔽了做菜 (底層)的實現(xiàn)。
步驟一
創(chuàng)建關(guān)于做菜一系列子功能:
-
買菜(Groceries):
/** * @see 做飯第一步,根據(jù)目標買菜 * @author Thornhill * */ public class Groceries { private List<String> names; public Groceries(List<String> names) { this.names = names; } public void buy() { System.out.println("買了" + names + "菜"); } }-
洗菜(Clean):
/** * @see 做菜第二步,清洗菜品 * @author Thornhill * */ public class Clean { public void clean(List<String> names) { System.out.println("洗" + names + "菜"); } }-
烹飪(Cooking):
/** * @see 做菜第三步,烹飪出鍋 * @author Thornhill * */ public class Cooking { public void cooking(List<String> names, String foodName) { System.out.println("烹飪" + names + "食材," + "產(chǎn)出" + foodName); } }
-
-
步驟二
創(chuàng)建門面對象,即廚師(Chef):
/**
* @see 告訴廚師,將屏蔽底層實現(xiàn),廚師知道買什么菜,怎么做飯。
* @author Thornhill
*
*/
public class Chef {
public void cooking(String foodName) {
List<String> names = new ArrayList<>();
switch (foodName) {
case "西紅柿雞蛋":
names.add("雞蛋");
names.add("西紅柿");
break;
case "京醬肉絲":
names.add("肉");
names.add("蔥");
break;
default:
System.out.println("您的廚師暫時不支持此功能");
return;
// break;
}
Groceries groceries = new Groceries(names);
// 完成購買
groceries.buy();
Clean clean = new Clean();
// 完成清洗
clean.clean(names);
Cooking cooking = new Cooking();
// 完成烹飪
cooking.cooking(names, foodName);
}
}
步驟三
創(chuàng)建用戶(User)使用:
/**
* @see 任性的用戶只需要提出需求使用即可,不需要關(guān)注具體的實現(xiàn)細節(jié)
* @author Thornhill
*
*/
public class User {
public static void main(String[] args) {
Chef chef = new Chef();
// 把想吃的菜告訴廚師
chef.cooking("西紅柿雞蛋");
chef.cooking("京醬肉絲");
chef.cooking("滿漢全席");
}
}
步驟四
測試輸出:
買了[雞蛋, 西紅柿]菜
洗[雞蛋, 西紅柿]菜
烹飪[雞蛋, 西紅柿]食材,產(chǎn)出西紅柿雞蛋
買了[肉, 蔥]菜
洗[肉, 蔥]菜
烹飪[肉, 蔥]食材,產(chǎn)出京醬肉絲
您的廚師暫時不支持此功能
結(jié)語:
外觀模式的應用非常廣泛,從系統(tǒng)的輪子到用戶的需求,都是屏蔽了細節(jié),只提供UI。不過要小心使用,因為這將極大程度違背了開閉原則,對將來的修改造成了困擾。