1. 介紹
1.1 定義&圖解
定義了一個(gè)高層拦盹、統(tǒng)一的接口坝疼,外部通過這個(gè)統(tǒng)一的接口對子系統(tǒng)中的一群接口進(jìn)行訪問。
通過創(chuàng)建一個(gè)統(tǒng)一的外觀類掖举,用來包裝子系統(tǒng)中一個(gè)或多個(gè)復(fù)雜的類朗徊,客戶端可以通過調(diào)用這個(gè)外觀類的方法來調(diào)用內(nèi)部子系統(tǒng)中所有方法首妖。
圖解:
外觀模式圖解1.png
網(wǎng)站的導(dǎo)航例子:以前我需要在搜索欄逐個(gè)搜索網(wǎng)站地址,有了網(wǎng)站導(dǎo)航(外觀模式)后爷恳,就方便很多了有缆,如下圖。
外觀模式圖解2.png
1.2 主要作用
- 實(shí)現(xiàn)客戶類與子系統(tǒng)類的松耦合温亲。
- 降低原有系統(tǒng)的復(fù)雜度棚壁。
- 提高了客戶端使用的便捷性,使得客戶端無須關(guān)心子系統(tǒng)的工作細(xì)節(jié)栈虚,通過外觀角色即可調(diào)用相關(guān)功能袖外。
- 引入外觀角色之后,用戶只需要與外觀角色交互魂务;
- 用戶與子系統(tǒng)之間的復(fù)雜邏輯關(guān)系由外觀角色來實(shí)現(xiàn)曼验。
1.3 解決的問題
- 避免了客戶端系統(tǒng)與子系統(tǒng)之間的高耦合度
- 使得復(fù)雜的子系統(tǒng)用法變得簡單
2. 模式原理
2.1 UML類圖 & 組成
外觀模式UML.png
2.2 實(shí)例講解
接下來我用一個(gè)實(shí)例來對建造者模式進(jìn)行更深一步的介紹。
a. 實(shí)例概況
- 背景:小成的爺爺已經(jīng)80歲了头镊,一個(gè)人在家生活蚣驼,每次起床后都需要打開燈、打開電視相艇、打開空調(diào);睡覺前都需要關(guān)閉燈纯陨、關(guān)閉電視坛芽、關(guān)閉空調(diào)。
- 沖突:行動(dòng)不方便翼抠,走過去關(guān)閉那么多電器很麻煩咙轩。
- 解決方案:小成買了一個(gè)智能家具控制器(外觀對象/統(tǒng)一接口)給他爺爺,他爺爺只需要一鍵就能打開/關(guān)閉 燈阴颖、電視機(jī)活喊、空調(diào)。
- 即用外觀模式來為所有子系統(tǒng)設(shè)計(jì)一個(gè)統(tǒng)一的接口
- 客戶端只需要調(diào)用外觀類中的方法就可以了量愧,簡化了客戶端的操作
b. 代碼如下
電器類
//燈類
public class SubSystemA_Light {
public void on(){
System.out.println("打開了燈...");
}
public void off(){
System.out.println("關(guān)閉了燈...");
}
}
//電視類
public class SubSystemB_Television {
public void on(){
System.out.println("打開了電視...");
}
public void off(){
System.out.println("關(guān)閉了電視...");
}
}
//空調(diào)類
public class SubSystemC_Aircondition {
public void on(){
System.out.println("打開了空調(diào)...");
}
public void off(){
System.out.println("關(guān)閉了空調(diào)...");
}
}
外觀類:智能遙控器
public class Facade {
private SubSystemA_Light light;
private SubSystemB_Television television;
private SubSystemC_Aircondition aircondition;
//構(gòu)造方法傳參
public Facade(SubSystemA_Light light,SubSystemB_Television television,SubSystemC_Aircondition aircondition){
this.light = light;
this.television = television ;
this.aircondition =aircondition;
}
//起床后一鍵開電器
public void on(){
System.out.println("起床了");
light.on();
television.on();
aircondition.on();
}
//睡覺時(shí)一鍵關(guān)電器
public void off(){
System.out.println("睡覺了");
light.off();
television.off();
aircondition.off();
}
}
客戶端調(diào)用
public class FacadePattern {
public static void main(String[] args){
SubSystemA_Light light = new SubSystemA_Light();
SubSystemB_Television television = new SubSystemB_Television();
SubSystemC_Aircondition aircondition = new SubSystemC_Aircondition();
/***********不使用外觀模式時(shí)的情況***********/
//起床后開電器
System.out.println("起床了");
light.on();
television.on();
aircondition.on();
System.out.println("可以看電視了");
//睡覺時(shí)關(guān)電器
System.out.println("睡覺了");
light.off();
television.off();
aircondition.off();
System.out.println("可以睡覺了");
System.out.println("----------------------------------------");
/***********使用外觀模式時(shí)的情況***********/
//外觀模式構(gòu)造方法傳參
Facade facade = new Facade(light,television,aircondition);
//客戶端直接與外觀對象進(jìn)行交互
facade.on();
System.out.println("可以看電視了");
facade.off();
System.out.println("可以睡覺了");
}
}
輸出結(jié)果
起床了
打開了燈...
打開了電視...
打開了空調(diào)...
可以看電視了
睡覺了
關(guān)閉了燈...
關(guān)閉了電視...
關(guān)閉了空調(diào)...
可以睡覺了
----------------------------------------
起床了
打開了燈...
打開了電視...
打開了空調(diào)...
可以看電視了
睡覺了
關(guān)閉了燈...
關(guān)閉了電視...
關(guān)閉了空調(diào)...
可以睡覺了
c. 解釋說明
- 從上面客戶端調(diào)用的情況可以看出钾菊,在不使用外觀模式的情況下帅矗,小成爺爺需要對每個(gè)電器都進(jìn)行操作,非常不方便煞烫。
- 客戶端與三個(gè)子系統(tǒng)都發(fā)送了耦合浑此,使得客戶端程序依賴與子系統(tǒng)。
3. 優(yōu)缺點(diǎn)
3.1 優(yōu)點(diǎn)
- 降低了客戶類與子系統(tǒng)類的耦合度滞详,實(shí)現(xiàn)了子系統(tǒng)與客戶之間的松耦合關(guān)系凛俱。
- 只是提供了一個(gè)訪問子系統(tǒng)的統(tǒng)一入口,并不影響用戶直接使用子系統(tǒng)類料饥。
- 減少了與子系統(tǒng)的關(guān)聯(lián)對象蒲犬,實(shí)現(xiàn)了子系統(tǒng)與客戶之間的松耦合關(guān)系,松耦合使得子系統(tǒng)的組件變化不會影響到它的客戶岸啡。
- 外觀模式對客戶屏蔽了子系統(tǒng)組件原叮,從而簡化了接口,減少了客戶處理的對象數(shù)目并使子系統(tǒng)的使用更加簡單凰狞。
- 引入外觀角色之后篇裁,用戶只需要與外觀角色交互;
- 用戶與子系統(tǒng)之間的復(fù)雜邏輯關(guān)系由外觀角色來實(shí)現(xiàn)赡若。
- 降低原有系統(tǒng)的復(fù)雜度和系統(tǒng)中的編譯依賴性达布,并簡化了系統(tǒng)在不同平臺之間的移植過程。
因?yàn)榫幾g一個(gè)子系統(tǒng)一般不需要編譯所有其他的子系統(tǒng)逾冬。一個(gè)子系統(tǒng)的修改對其他子系統(tǒng)沒有任何影響黍聂,而且子系統(tǒng)內(nèi)部變化也不會影響到外觀對象。
3.2 缺點(diǎn)
- 在不引入抽象外觀類的情況下身腻,增加新的子系統(tǒng)可能需要修改外觀類或客戶端的源代碼产还,違背了“開閉原則”。
- 不能很好地限制客戶使用子系統(tǒng)類嘀趟,如果對客戶訪問子系統(tǒng)類做太多的限制則減少了可變性和靈活性脐区。
4. 應(yīng)用場景
- 要為一個(gè)復(fù)雜的子系統(tǒng)對外提供一個(gè)簡單的接口。
- 提供子系統(tǒng)的獨(dú)立性她按。
- 客戶程序與多個(gè)子系統(tǒng)之間存在很大的依賴性牛隅。
引入外觀類將子系統(tǒng)與客戶以及其他子系統(tǒng)解耦,可以提高子系統(tǒng)的獨(dú)立性和可移植性酌泰。
- 在層次化結(jié)構(gòu)中媒佣,可以使用外觀模式定義系統(tǒng)中每一層的入口。
層與層之間不直接產(chǎn)生聯(lián)系陵刹,而通過外觀類建立聯(lián)系默伍,降低層之間的耦合度。