基本概念
外觀模式(Facade),也叫“過程模式”。外觀模式為子系統中的一組接口提供一個一致的界面,此模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。
外觀模式通過定義一個一致的接口,用以屏蔽內部子系統的細節,使得調用端只需跟這個接口發生調用, 而無需關心這個子系統的內部細節。
外觀模式可以理解為轉換一群接口,客戶只要調用一個接口,而不用調用多個接口才能達到目的。比如,在pc上安裝軟件的時候經常有一鍵安裝選項(省去選擇安裝目錄、安裝的組件等等),還有就是手機的重啟功能(把關機和啟動合為一個操作)。
外觀模式就是解決多個復雜接口帶來的使用困難,起到簡化用戶操作的作用。
外觀模式原理類圖:

- 外觀類(Facade):為調用端提供統一的調用接口,外觀類知道哪些子系統負責處理請求,從而將調用端的請求代理給適當子系統對象。
- 調用者(CLient):外觀接口的調用者。
- 子系統的集合:指模塊或者子系統,處理Facade對象指派的任務,它是功能的實際提供者。
傳統方式
案例
影院管理項目:組建一個家庭影院:DVD播放器、投影儀、自動屏幕、環繞立體聲、爆米花機,要求完成使用家庭影院的功能,其過程為使用遙控器統籌各設備開關。
思路分析

問題分析
在ClientTest的main方法中,創建各個子系統的對象,並直接區調用子系統(對象)相關方法,會造成調用過程混亂,沒有清晰的過程。
不利於在ClientTest中,去維護對子系統的操作。
解決思路:定義一個高層接口,給子系統中的一組接口提供一個一致的界面(比如在高層接口提供三個方法ready,play,end),用來訪問子系統中的一群接口。
也就是說,就是通過定義一個一致的接口(界面類),用以屏蔽內部子系統的細節,使得調用端只需跟這個接口發生調用,而無需關心這個子系統的內部細節(外觀模式)。
外觀模式
思路分析

代碼實現
1public class DVDPlayer {
2
3 //使用單例模式,使用餓漢式
4 private static DVDPlayer instance=new DVDPlayer();
5
6 private DVDPlayer(){//構造器私有化
7 }
8
9 public static DVDPlayer getInstance(){
10 return instance;
11 }
12
13 public void on(){
14 System.out.println("DVD打開");
15 }
16
17 public void off(){
18 System.out.println("DVD關閉");
19 }
20
21 public void play(){
22 System.out.println("DVD正在播放");
23 }
24}
1public class Popcorn {
2
3 private static Popcorn instance=new Popcorn();
4
5 private Popcorn(){
6 }
7
8 public static Popcorn getInstance(){
9 return instance;
10 }
11
12 public void on(){
13 System.out.println("爆米花機打開");
14 }
15
16 public void off(){
17 System.out.println("爆米花機關閉");
18 }
19
20 public void pop(){
21 System.out.println("爆米花機正在制作爆米花");
22 }
23}
1public class Projector {
2
3 private static Projector instance=new Projector();
4
5 private Projector(){
6 }
7
8 public static Projector getInstance(){
9 return instance;
10 }
11
12 public void on(){
13 System.out.println("投影儀打開");
14 }
15
16 public void off(){
17 System.out.println("投影儀關閉");
18 }
19
20 public void focus(){
21 System.out.println("投影儀正在聚焦");
22 }
23}
1public class Screen {
2
3 private static Screen instance=new Screen();
4
5 private Screen(){
6 }
7
8 public static Screen getInstance(){
9 return instance;
10 }
11
12 public void up(){
13 System.out.println("屏幕上升");
14 }
15
16 public void down(){
17 System.out.println("屏幕下降");
18 }
19}
1public class Stereo {
2
3 private static Stereo instance=new Stereo();
4
5 private Stereo(){
6 }
7
8 public static Stereo getInstance(){
9 return instance;
10 }
11
12 public void on(){
13 System.out.println("立體聲打開");
14 }
15
16 public void off(){
17 System.out.println("立體聲關閉");
18 }
19}
1public class TheaterLight {
2
3 private static TheaterLight instance=new TheaterLight();
4
5 private TheaterLight(){
6 }
7
8 public static TheaterLight getInstance(){
9 return instance;
10 }
11
12 public void on(){
13 System.out.println("燈光打開");
14 }
15
16 public void off(){
17 System.out.println("燈光關閉");
18 }
19
20}
1public class HomeTheaterFacade {
2
3 //定義各個子系統對象
4 private TheaterLight theaterLight;
5 private Popcorn popcorn;
6 private Stereo stereo;
7 private Projector projector;
8 private Screen screen;
9 private DVDPlayer dvdPlayer;
10
11 public HomeTheaterFacade() {
12 this.theaterLight = TheaterLight.getInstance();
13 this.popcorn = Popcorn.getInstance();
14 this.stereo = Stereo.getInstance();
15 this.projector = Projector.getInstance();
16 this.screen = Screen.getInstance();
17 this.dvdPlayer = DVDPlayer.getInstance();
18 }
19
20 //操作分為四步
21 public void ready(){
22 theaterLight.on();
23 projector.on();
24 popcorn.on();
25 stereo.on();
26 screen.up();
27 dvdPlayer.on();
28 }
29
30 public void play(){
31 dvdPlayer.play();
32 }
33
34 public void end(){
35 theaterLight.off();
36 projector.off();
37 popcorn.off();
38 stereo.off();
39 screen.down();
40 dvdPlayer.off();
41 }
42}
1public class Client {
2
3 public static void main(String[] args) {
4 HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade();
5 homeTheaterFacade.ready();
6 homeTheaterFacade.play();
7 homeTheaterFacade.end();
8 }
9}
注意事項
外觀模式對外屏蔽了子系統的細節,因此外觀模式降低了客戶端對子系統使用的復雜性。
外觀模式對客戶端與子系統的耦合關系—解耦,讓子系統內部的模塊更易維護和擴展。
通過合理的使用外觀模式,可以幫我們更好的划分訪問的層次。
當系統需要進行分層設計時,可以考慮使用Facade模式。
在維護一個遺留的大型系統時,可能這個系統已經變得非常難以維護和擴展,此時可以考慮為新系統開發一個Facade類,來提供遺留系統的比較清晰簡單的接口,讓新系統與Facade類交互,提高復用性。
不能過多的或者不合理的使用外觀模式,要讓系統有層次,利於維護為目的。