一、舉個栗子
小明每天回家都會先打開燈,空氣凈化器,電熱水器燒上水,放上音樂,如果天氣熱的話,再打開空調。
寫成代碼
lights.on();//打開燈
airCleaner.on();//打開空氣凈化器
airCleaner.setMode(auto);//設置自動模式
waterHeater.on();//打開電熱水器
waterHeater.setTemperature(40);//水溫40度
player.on();//打開音響
play.play(music);//放上音樂
...
//涉及到太多類了!!!
出門的時候,還得反向操作把它們都關掉。
如果升級了系統,還得重新學習另一套操作流程。
那么就使用外觀模式來改造成智能家居吧。
二、設計思路
1、創建一個名為HomeFacade新類,對外暴露幾個簡單的方法,如open()
2、這個新類把燈,音響,空調等視為子系統,讓open()去調用他們
3、客戶端去調用HomeFacade所提供的方法,而無須再分步驟調用子系統,就可以完成所有操作
image.png
外觀只提供更直接的操作,并沒有將原來的子系統隔離起來,還是可以調用原來的子系統的。
具體實現:
public class HomeFacade {
//所用到的子系統組件
musicPlayer player;
Light light;
...
//將子系統的每個組件傳入構造器,并賦值給實例變量
public HomeFacade(musicPlayer player, Light light, ...) {
this.player = player;
this.light = light;
...
}
public void open() {
lights.on();//打開燈
airCleaner.on();//打開空氣凈化器
airCleaner.setMode(auto);//設置自動模式
waterHeater.on();//打開電熱水器
waterHeater.setTemperature(40);//水溫40度
player.on();//打開音響
play.play(music);//放上音樂
}
public void endMovie() {
lights.off();
airCleaner.off();
waterHeater.();
...
}
}
//進家門
public class HomeTestDrive {
public static void main(String[] args) {
HomeFacade home = new HomeFacade(player, light, ...);
//使用簡化的接口,打開各種電器,然后關閉各種電器
home.open();
home.close();
}
}
三、外觀模式
1、定義:
外觀模式提供了一個統一的接口,用來訪問子系統中的一群接口,外觀定義了一個高層接口,讓子系統更容易使用。
外觀模式封裝了子系統的操作,暴露一個統一的接口讓用戶使用,避免了用戶需要與多個子系統進行交互,降低了系統的耦合度、復雜度。如果沒有外觀模式的封裝,那么用戶就必須知道各個子系統的相關細節,子系統之間的交互必然造成糾纏不清的關系,影響系統的穩定性、復雜度。
2、類圖
image.png
Tips:
最少知識原則:要減少對象間的交互,只和密友交談。也就是說,不要讓太多的類耦合在一起,避免修改系統中的一部分,會影響其他部分,如果許多類之間相互依賴,那這個系統的維護成本就會很高,也不容易被他人了解。
3、與裝飾者模式,適配器模式的區別
裝飾者模式是將一個對象包裝起來,增加新的行為和責任
image.png
適配器模式是現有類的接口不符合需要,必須轉換成不同的接口,(將一個對象包裝起來改變接口)以符合客戶的期望
外觀模式可以簡化并統一一個很大很復雜的接口,(將對象“包裝”起來簡化接口)將用戶從組件的子系統中解耦
image.png
四、外觀模式在Android中的應用
在Android中,Context是最重要的一個類型。它封裝了很多重要的操作,比如startActivity()、sendBroadcast()等,這些功能內部的實現非常復雜,但是我們無需關心它內部實現了什么,我們只關心它幫我們啟動Activity,幫我們發送了一條廣播,綁定了Activity等等就夠了。
Context是一個抽象類,它只是定義了抽象接口,真正的實現在ContextImpl類中,在ContextImpl內部有很多xxxManager類的對象,也就是前面所說的各種子系統。
image.png