設計模式之外觀模式案例詳解


基本概念

外觀模式(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類交互,提高復用性。

不能過多的或者不合理的使用外觀模式,要讓系統有層次,利於維護為目的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM