結構型 - 外觀
提供了一個統一的接口,用來訪問子系統中的一群接口,從而讓子系統更容易使用。
public class SubSystem {public void turnOnTV() {System.out.println("turnOnTV()");}public void setCD(String cd) {System.out.println("setCD( " + cd + " )");}public void starWatching(){System.out.println("starWatching()");}
}
public class Facade {private SubSystem subSystem = new SubSystem();public void watchMovie() {subSystem.turnOnTV();subSystem.setCD("a movie");subSystem.starWatching();}
}public class Client {public static void main(String[] args) {Facade facade = new Facade();facade.watchMovie();}
}
使用的場景?
簡化復雜系統:當系統內部由多個子系統組成,并且這些子系統之間相互依賴,外觀模式可以提供一個統一的入口,簡化使用。
解耦客戶端和子系統:當客戶端需要與多個子系統交互時,使用外觀模式可以減少客戶端對子系統的直接依賴,降低耦合度。
隱藏實現細節:當系統內部的實現經常變化,而希望客戶端代碼盡量少受影響時,可以使用外觀模式隱藏這些變化。
提供統一接口:對外暴露一個簡單、穩定的接口,避免讓用戶直接面對復雜的底層系統本質是什么?
外觀模式的本質是 封裝復雜性,提供統一訪問接口。它通過創建一個“門面”(Facade)類,封裝多個子系統的調用,使得客戶端可以通過這個門面類來訪問系統,而不需要了解系統的復雜內部結構。它解決了什么問題?
外觀模式主要解決 降低復雜系統的使用難度和客戶端的依賴性。
降低耦合:客戶端不需要直接依賴多個子系統,而是通過外觀類進行交互。
提高可維護性:當子系統發生變化時,只需要修改外觀類,而不需要修改所有使用子系統的代碼。
增強可讀性:提供一個統一的、高層次的接口,使得代碼更清晰、更易理解。它體現了設計模式中什么原則?
迪米特法則(最少知道原則,LoD):外觀模式減少了對象之間的直接交互,客戶端只需要知道外觀類,而不需要了解具體的子系統。
單一職責原則(SRP):外觀類的職責是提供一個簡化的接口,而不是處理子系統的業務邏輯。
依賴倒置原則(DIP):高層模塊(客戶端)不應該依賴低層模塊(子系統),而是通過外觀類進行依賴。存在的缺陷?
可能導致“上帝類”:如果外觀類封裝過多邏輯,可能會變得過于龐大,形成“上帝類”(God Object),降低可維護性。
降低靈活性:如果客戶端需要訪問子系統的某些高級功能,而外觀類沒有提供接口,那么客戶端仍然需要直接訪問子系統,削弱了外觀模式的意義。
可能引入性能問題:如果外觀類封裝了過多的子系統調用,而每次客戶端調用外觀類時都會觸發所有子系統調用,可能會降低性能。你認為與它相關的設計模式有哪些? 它們之間的區別有哪些?
中介者模式(Mediator):
相似點:都用于降低對象之間的直接交互,提高模塊解耦性。
區別:外觀模式是為多個子系統提供統一入口,而中介者模式則是管理多個對象之間的交互關系,通常用于對象之間的通信,而非子系統之間的封裝。適配器模式(Adapter):
相似點:都對現有系統進行了封裝,以提供更方便的使用方式。
區別:適配器模式用于接口轉換,使不兼容的接口能夠協同工作,而外觀模式只是提供一個簡化的接口,并不改變子系統的行為。代理模式(Proxy):
相似點:都為客戶端提供了一個間接訪問的方式。
區別:代理模式通常用于控制對某個對象的訪問,例如增加權限控制、緩存,而外觀模式的主要目的是簡化接口。*開源架構中哪些使用了這一模式?
Spring Framework
Spring 的 JdbcTemplate 就是外觀模式的一個例子,它封裝了 JDBC 的底層復雜邏輯,使得開發者可以更簡單地執行 SQL 語句。
RestTemplate 也是外觀模式,它對 HTTP 客戶端進行封裝,使得調用 REST API 變得簡單。MyBatis
SqlSession 作為外觀類,封裝了底層數據庫操作,使得開發者可以通過一個簡單的 API 進行數據庫查詢。Dubbo
Dubbo 的 ServiceProxy 代理遠程調用細節,對外提供一個簡潔的調用方式。Log4j/SLF4J
SLF4J 是日志框架的外觀模式,它統一了 Log4j、Logback 等日志實現,提供一個統一的 API,減少了對具體日志實現的依賴。