1. 程式人生 > 實用技巧 >10.java設計模式之外觀模式

10.java設計模式之外觀模式

基本需求:

  • 組建一個家庭影院: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類互動,提高複用性
  • 不能過多的或者不合理的使用外觀模式,使用外觀模式好,還是直接呼叫模組好。要以讓系統有層次,利於維護為目的