10.java設計模式之外觀模式
阿新 • • 發佈:2020-11-19
基本需求:
- 組建一個家庭影院:DVD 播放器、投影儀、自動螢幕、環繞立體聲、爆米花機,要求完成使用家庭影院的功能,
- 其過程為:直接用遙控器:統籌各裝置開關
- 開爆米花機、放下螢幕、開投影儀、開音響、開 DVD,選 dvd、去拿爆米花、調暗燈光、播放、觀影結束後,關閉各種裝置
傳統方案:
- 客戶端直接依賴各種裝置,直接呼叫各種裝置的方法
- UML類圖
- 在Client中,建立各個子系統的物件,並直接去呼叫子系統(物件)相關方法,會造成呼叫過程混亂,沒有清晰的過程,不利於維護
- 定義一個高層介面,給子系統中的一組介面提供一個一致的介面(比如在高層介面提供四個方法ready, play, pause, end),用來訪問子系統中的一群介面,就是通過定義一個一致的介面(介面類),用以遮蔽內部子系統的細節,使得呼叫端只需跟這個介面發生呼叫,而無需關心這個子系統的內部細節 -> 外觀模式
基本介紹:
-
外觀模式(Facade)隱藏系統的複雜性,並向客戶端提供了一個客戶端可以訪問系統的介面。這種型別的設計模式屬於結構型模式,它向現有的系統新增一個介面,來隱藏系統的複雜性。這種模式涉及到一個單一的類,該類提供了客戶端請求的簡化方法和對現有系統類方法的委託呼叫
-
為子系統中的一組介面提供一個一致的介面,外觀模式定義了一個高層介面,這個介面使得這一子系統更加容易使用
-
主要解決:降低訪問複雜系統的內部子系統時的複雜度,簡化客戶端與之的介面
-
UMl類圖(原理)
- Facade類為外觀類,聚合了其他多個子系統(實際功能的提供者),讓client統一呼叫
-
UML類圖(案例)
-
程式碼實現
-
public class DVDPlayer { // DVD播放器 使用餓漢 public static final DVDPlayer DVD_PLAYER = new DVDPlayer(); private DVDPlayer() { } public static DVDPlayer getInstance() { return DVD_PLAYER; } public void on() { System.out.println("dvd on"); } public void off() { System.out.println("dvd off"); } public void play() { System.out.println("dvd play"); } public void pause() { System.out.println("dvd pause"); } }
-
public class Screen { // 螢幕 使用餓漢 public static final Screen SCREEN = new Screen(); private Screen() { } public static Screen getInstance() { return SCREEN; } public void up() { System.out.println("screen up"); } public void dowm() { System.out.println("screen down"); } }
-
public class Popcorn { // 爆米花機 使用餓漢 public static final Popcorn POPCORN = new Popcorn(); private Popcorn() { } public static Popcorn getInstance() { return POPCORN; } public void on() { System.out.println("popcorn on"); } public void off() { System.out.println("popcorn off"); } public void pop() { System.out.println("popcorn pop"); } }
-
public class Projector { // 投影儀 使用餓漢 public static final Projector PROJECTOR = new Projector(); private Projector() { } public static Projector getInstance() { return PROJECTOR; } public void on() { System.out.println("projector on"); } public void off() { System.out.println("projector off"); } public void focus() { System.out.println("projector focus"); } }
-
public class TheaterLight { // 影院燈光 使用餓漢 public static final TheaterLight THEATER_LIGHT = new TheaterLight(); private TheaterLight() { } public static TheaterLight getInstance() { return THEATER_LIGHT; } public void on() { System.out.println("theater_light on"); } public void off() { System.out.println("theater_light off"); } public void dim() { System.out.println("theater_light dim"); } public void bright() { System.out.println("theater_light bright"); } }
-
public class Stereo { // 立體聲 使用餓漢 public static final Stereo STEREO = new Stereo(); private Stereo() { } public static Stereo getInstance() { return STEREO; } public void on() { System.out.println("stereo on"); } public void off() { System.out.println("stereo off"); } public void up() { System.out.println("stereo up"); } }
-
public class HomeTheaterFacade { // 影院外觀類,聚合其他子系統 ,提供統一的方法供Client呼叫 private DVDPlayer dvdPlayer = DVDPlayer.getInstance(); private Screen screen = Screen.getInstance(); private Popcorn popcorn = Popcorn.getInstance(); private Projector projector = Projector.getInstance(); private TheaterLight theaterLight = TheaterLight.getInstance(); private Stereo stereo = Stereo.getInstance(); public HomeTheaterFacade() { } // 給Client提供的方法相當於子系統方法的集合 public void ready() { popcorn.on(); popcorn.pop(); screen.dowm(); projector.on(); projector.focus(); theaterLight.on(); stereo.on(); dvdPlayer.on(); } public void play() { theaterLight.dim(); stereo.up(); dvdPlayer.play(); } public void pause() { dvdPlayer.pause(); } public void end() { popcorn.off(); screen.up(); projector.off(); theaterLight.off(); stereo.off(); dvdPlayer.off(); } }
-
public class Client { public static void main(String[] args) { HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade(); System.out.println("-----------ready-----------"); homeTheaterFacade.ready(); System.out.println("-----------play-----------"); homeTheaterFacade.play(); System.out.println("-----------pause-----------"); homeTheaterFacade.pause(); System.out.println("-----------end-----------"); homeTheaterFacade.end(); } }
-
mybatis原始碼:
- 在mybatis的configuration類中的newMetaObject方法中建立MetaObject時使用的構造方法中就用到的外觀模式
- UML類圖
- configuration類就相當於facade類
注意事項:
- 外觀模式對外遮蔽了子系統的細節,因此外觀模式降低了客戶端對子系統使用的複雜性
- 外觀模式對客戶端與子系統的耦合關係 - 解耦,讓子系統內部的模組更易維護和擴充套件
- 通過合理的使用外觀模式,可以幫我們更好的劃分訪問的
- 當系統需要進行分層設計時,可以考慮使用Facade模式(三層架構)
- 在維護一個遺留的大型系統時,可能這個系統已經變得非常難以維護和擴充套件,此時可以考慮為新系統開發一個Facade類,來提供遺留系統的比較清晰簡單的介面,讓新系統與Facade類互動,提高複用性
- 不能過多的或者不合理的使用外觀模式,使用外觀模式好,還是直接呼叫模組好。要以讓系統有層次,利於維護為目的