上篇文章咱們學習了適配器模式,咱們知道它是將一個接口轉換成另外一個符合用戶指望的接口,它的主要目的是爲了兼容,將一個不兼容接口的對象包裝起來,變成兼容的對象。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 圖以下:
下面來總結一下門面模式的優勢:
缺點:
其實門面模式很好地符合了最少知道原則,它指的是儘可能減小對象之間的交互。在設計中,咱們應該減小類之間的耦合度,以避免修改系統中一部分,而影響到其餘部分。
爲知足該原則,咱們應該只調用屬於如下範圍的方法:
例以下面的例子就符合最少知識原則:
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,而不須要關心日誌具體的實現。
日誌門面和日誌實現主要有:
具體它們的原理,這裏就不說了。
在實際使用時,例如 SpringBoot 中默認使用 Slfj + Logback 組合來打印日誌。