一、舉個(gè)栗子
小明每天回家都會(huì)先打開(kāi)燈,空氣凈化器,電熱水器燒上水,放上音樂(lè),如果天氣熱的話,再打開(kāi)空調(diào)。
寫(xiě)成代碼
lights.on();//打開(kāi)燈
airCleaner.on();//打開(kāi)空氣凈化器
airCleaner.setMode(auto);//設(shè)置自動(dòng)模式
waterHeater.on();//打開(kāi)電熱水器
waterHeater.setTemperature(40);//水溫40度
player.on();//打開(kāi)音響
play.play(music);//放上音樂(lè)
...
//涉及到太多類(lèi)了?。?!
出門(mén)的時(shí)候,還得反向操作把它們都關(guān)掉。
如果升級(jí)了系統(tǒng),還得重新學(xué)習(xí)另一套操作流程。
那么就使用外觀模式來(lái)改造成智能家居吧。
二、設(shè)計(jì)思路
1、創(chuàng)建一個(gè)名為HomeFacade新類(lèi),對(duì)外暴露幾個(gè)簡(jiǎn)單的方法,如open()
2、這個(gè)新類(lèi)把燈,音響,空調(diào)等視為子系統(tǒng),讓open()去調(diào)用他們
3、客戶(hù)端去調(diào)用HomeFacade所提供的方法,而無(wú)須再分步驟調(diào)用子系統(tǒng),就可以完成所有操作

外觀只提供更直接的操作,并沒(méi)有將原來(lái)的子系統(tǒng)隔離起來(lái),還是可以調(diào)用原來(lái)的子系統(tǒng)的。
具體實(shí)現(xiàn):
public class HomeFacade {
//所用到的子系統(tǒng)組件
musicPlayer player;
Light light;
...
//將子系統(tǒng)的每個(gè)組件傳入構(gòu)造器,并賦值給實(shí)例變量
public HomeFacade(musicPlayer player, Light light, ...) {
this.player = player;
this.light = light;
...
}
public void open() {
lights.on();//打開(kāi)燈
airCleaner.on();//打開(kāi)空氣凈化器
airCleaner.setMode(auto);//設(shè)置自動(dòng)模式
waterHeater.on();//打開(kāi)電熱水器
waterHeater.setTemperature(40);//水溫40度
player.on();//打開(kāi)音響
play.play(music);//放上音樂(lè)
}
public void endMovie() {
lights.off();
airCleaner.off();
waterHeater.();
...
}
}
//進(jìn)家門(mén)
public class HomeTestDrive {
public static void main(String[] args) {
HomeFacade home = new HomeFacade(player, light, ...);
//使用簡(jiǎn)化的接口,打開(kāi)各種電器,然后關(guān)閉各種電器
home.open();
home.close();
}
}
三、外觀模式
1、定義:
外觀模式提供了一個(gè)統(tǒng)一的接口,用來(lái)訪問(wèn)子系統(tǒng)中的一群接口,外觀定義了一個(gè)高層接口,讓子系統(tǒng)更容易使用。
外觀模式封裝了子系統(tǒng)的操作,暴露一個(gè)統(tǒng)一的接口讓用戶(hù)使用,避免了用戶(hù)需要與多個(gè)子系統(tǒng)進(jìn)行交互,降低了系統(tǒng)的耦合度、復(fù)雜度。如果沒(méi)有外觀模式的封裝,那么用戶(hù)就必須知道各個(gè)子系統(tǒng)的相關(guān)細(xì)節(jié),子系統(tǒng)之間的交互必然造成糾纏不清的關(guān)系,影響系統(tǒng)的穩(wěn)定性、復(fù)雜度。
2、類(lèi)圖

Tips:
最少知識(shí)原則:要減少對(duì)象間的交互,只和密友交談。也就是說(shuō),不要讓太多的類(lèi)耦合在一起,避免修改系統(tǒng)中的一部分,會(huì)影響其他部分,如果許多類(lèi)之間相互依賴(lài),那這個(gè)系統(tǒng)的維護(hù)成本就會(huì)很高,也不容易被他人了解。
3、與裝飾者模式,適配器模式的區(qū)別
裝飾者模式是將一個(gè)對(duì)象包裝起來(lái),增加新的行為和責(zé)任

適配器模式是現(xiàn)有類(lèi)的接口不符合需要,必須轉(zhuǎn)換成不同的接口,(將一個(gè)對(duì)象包裝起來(lái)改變接口)以符合客戶(hù)的期望
外觀模式可以簡(jiǎn)化并統(tǒng)一一個(gè)很大很復(fù)雜的接口,(將對(duì)象“包裝”起來(lái)簡(jiǎn)化接口)將用戶(hù)從組件的子系統(tǒng)中解耦

四、外觀模式在Android中的應(yīng)用
在Android中,Context是最重要的一個(gè)類(lèi)型。它封裝了很多重要的操作,比如startActivity()、sendBroadcast()等,這些功能內(nèi)部的實(shí)現(xiàn)非常復(fù)雜,但是我們無(wú)需關(guān)心它內(nèi)部實(shí)現(xiàn)了什么,我們只關(guān)心它幫我們啟動(dòng)Activity,幫我們發(fā)送了一條廣播,綁定了Activity等等就夠了。
Context是一個(gè)抽象類(lèi),它只是定義了抽象接口,真正的實(shí)現(xiàn)在ContextImpl類(lèi)中,在ContextImpl內(nèi)部有很多xxxManager類(lèi)的對(duì)象,也就是前面所說(shuō)的各種子系統(tǒng)。
