門面模式就是這麼簡單

上篇文章咱們學習了適配器模式,咱們知道它是將一個接口轉換成另外一個符合用戶指望的接口,它的主要目的是爲了兼容,將一個不兼容接口的對象包裝起來,變成兼容的對象。java

這篇文章咱們來學習一下門面模式,它又稱爲外觀模式,與適配器模式看起來很相似,但它主要是爲了簡化接口,下面就來具體看一下。設計模式

門面模式

不知道你們平時是否有這樣的經歷。天天開啓電腦後,要打開各類軟件、IDE、工具,就須要一個一個地點擊桌面圖標;到了晚上又要一個個地關閉,感受很是麻煩。框架

這裏舉幾個例子,首先是 Intellj IDEA:ide

public class IDEA {

    public void on() {
        System.out.println("打開 IDEA");
    }
    public void off() {
        System.out.println("關閉 IDEA");
    }
}
複製代碼

而後是 Google:工具

public class Google {

    private List<Tab> tabs = new ArrayList<>();

    public void on() {
        System.out.println("打開 google");
    }
    public void off() {
        System.out.println("關閉 google");
    }
    public void onTabs() {
        System.out.println("打開 ProcessOn、七牛雲等 Tab");
    }
}
複製代碼

還有有道雲筆記:學習

public class YouDaoNote {
    public void on() {
        System.out.println("打開 YouDaoNote");
    }
    public void off() {
        System.out.println("關閉 YouDaoNote");
    }
}
複製代碼

可能還會有 Weixin:ui

public class WeiXin {

    public void on() {
        System.out.println("打開 WeiXin");
    }
    public void off() {
        System.out.println("關閉 WeiXin");
    }
}
複製代碼

另外,可能還會有 Shell、CloudMusic 等。咱們開啓軟件時,能夠以下寫:this

public class Client {

    public static void main(String[] args) {
        IDEA idea = new IDEA();
        Google google = new Google();
        YouDaoNote youDaoNote = new YouDaoNote();
        WeiXin weiXin = new WeiXin();

        idea.on();
        google.on();
        google.onTabs();
        youDaoNote.on();
        weiXin.on();
    }
}
複製代碼

在關閉時,又將這些步驟反過來執行一遍,那也太麻煩了。其實,咱們能夠寫一個 bat 腳本,每次只須要執行這個腳本,就能夠開啓多個軟件。google

這個腳本就是所謂的門面,如今咱們來建立一個門面,它將不一樣的軟件組合成一個統一的接口:idea

public class DevelopmentEnvironment {

    private IDEA idea;
    private Google google;
    private YouDaoNote youDaoNote;
    private WeiXin weiXin;
    public DevelopmentEnvironment(IDEA idea, Google google, YouDaoNote youDaoNote, WeiXin weiXin) {
        this.idea = idea;
        this.google = google;
        this.youDaoNote = youDaoNote;
        this.weiXin = weiXin;
    }

    public void buildEnvironment() {
        idea.on();
        google.on();
        google.onTabs();
        youDaoNote.on();
        weiXin.on();
    }
    public void shutEnvironment() {
        idea.off();
        google.off();
        youDaoNote.off();
        weiXin.off();
    }
}
複製代碼

它對外只暴露了幾個方法,因而咱們創建開發環境能夠這樣寫:

public class Client {

    public static void main(String[] args) {
        IDEA idea = new IDEA();
        Google google = new Google();
        YouDaoNote youDaoNote = new YouDaoNote();
        WeiXin weiXin = new WeiXin();

        DevelopmentEnvironment environment = new DevelopmentEnvironment(idea, google, youDaoNote, weiXin);
        environment.buildEnvironment();
    }
}
複製代碼

上述模式就是門面模式,它提供了一個統一的接口,來訪問子系統的多個接口,使得子系統更容易使用。

它的 UML 圖以下:

下面來總結一下門面模式的優勢:

  • 經過統一的接口,來訪問子系統的多個接口。如此就無需瞭解子系統的實現,簡化了調用的過程。
  • 減小了客戶和子系統之間的系統依賴,耦合度更低。
  • 門面模式很好得符合了最少知道原則。

缺點:

  • 若是增長子系統,或者擴展子系統的行爲,可能會引入風險;
  • 系統設計不當時,增長子系統可能須要修改門面類,這違背了開閉原則。

最少知道原則

其實門面模式很好地符合了最少知道原則,它指的是儘可能減小對象之間的交互。在設計中,咱們應該減小類之間的耦合度,以避免修改系統中一部分,而影響到其餘部分。

爲知足該原則,咱們應該只調用屬於如下範圍的方法:

  1. 該對象自己;
  2. 被看成方法的參數而傳遞進來的對象;
  3. 此方法所建立或實例化的任何對象;
  4. 對象的任何組件;

例以下面的例子就符合最少知識原則:

public class Car {
    Engine engine; // 對象的組件
    
    public Car() {}
    
    // key 爲做爲方法參數傳遞進來的對象
    public void start(Key key) {
        Door door = new Door(); // 該方法中建立的對象
        
        boolean authorized = key.turn(); // 調用做爲方法參數傳遞進來的對象的方法,2
        if(authorized) {
            engine.start(); // 調用組件的方法 // 4
            updateDashboardDisplay(); // 調用對象自己的方法 // 1
            door.lock(); // 調用該方法中建立的對象的方法 // 2
        }
    }
    
    // 對象自己的方法
    public void updateDasnboardDisplay() {}
}
複製代碼

門面模式的具體實踐

在實際項目中,咱們都會記錄應用的執行日誌,經常使用的日誌框架有許多,而不一樣的中間件會集成不一樣的日誌框架,當集成這些中間件時,咱們的系統不得不維護去多種日誌框架。

因而,咱們能夠引入一箇中間層,由這個中間層來決定使用哪個具體的日誌實現。這個中間層就是日誌門面,咱們在打印日誌時,只須要調用日誌門面的 API,而不須要關心日誌具體的實現。

日誌門面和日誌實現主要有:

  • 日誌門面(日誌的抽象層):slf4j、jcl(commons-logging);
  • 日誌實現:jul(java.util.logging)、logback、log4j、log4j2;

具體它們的原理,這裏就不說了。

在實際使用時,例如 SpringBoot 中默認使用 Slfj + Logback 組合來打印日誌。

參考資料

  • 《Head First 設計模式》
相關文章
相關標籤/搜索