從源碼角度理解Java設計模式——門面模式

一、門面模式介紹

門面模式定義:也叫外觀模式,定義了一個訪問子系統的接口,除了這個接口以外,不允許其他訪問子系統的行為發生。

適用場景:子系統很複雜時,增加一個接口供外部訪問。

優點:簡化層級間的調用,減少依賴,防止風險。

缺點:如果設計不當,增加新的子系統可能需要修改門面類的源代碼,違背了開閉原則。

類型:結構型。

類圖:

從源碼角度理解Java設計模式——門面模式

二、門面模式簡單實例

小明想開一個餐館,要去政府部門辦理衛生許可證、辦理稅務登記和辦理工商登記,以前小王要一一親自去辦理,這不是一件容易的事。

政府最近簡化了政務辦理流程,只用小明訪問一次簡化政務辦理的門面就可以辦理到全部證件。

從源碼角度理解Java設計模式——門面模式

測試一下:

從源碼角度理解Java設計模式——門面模式

三、日誌門面

阿里巴巴開發手冊中有這樣一條規定:

從源碼角度理解Java設計模式——門面模式

其中Log4j、Logback都是日誌框架,它們都有著自己的獨立的Api接口。如果單獨使用某個框架,會大大增加系統的耦合性。而SLF4J並不是真正的日誌框架,它有一套通用的API接口。

所以阿里開發手冊中直接強制用SLF4J日誌門面,日誌門面是門面模式的一個典型應用。SLF4J的helloworld如下:

從源碼角度理解Java設計模式——門面模式

進入info方法:

從源碼角度理解Java設計模式——門面模式

上圖的SubstituteLogger.class裡還是調用Logger接口的info方法,NOPLogger如同它的名字一樣:什麼都不做,所以只有在系統引入Logback這個日誌框架時,才有了Logger真正的實現類。那Log4j、Logback等日誌框架是怎麼和SLF4J對接的?

任何日誌框架,一定都是通過自己的StaticLoggerBinder類來和SLF4J對接:

從源碼角度理解Java設計模式——門面模式

這個類的實現,在不同的框架中,實現不同,以Logback為例:

從源碼角度理解Java設計模式——門面模式

這個實現的類被設計為或者簡單的返回一個默認的LoggerContext(LoggerContext是ILoggerFactory在logback中的實現),或者通過ContextSelector(logback特有的)來選擇一個LoggerContext並返回。

四、源碼中的門面模式

3.1 Spring JDBC中的JdbcUtils對原生的JDBC進行封裝,讓調用者統一訪問。

從源碼角度理解Java設計模式——門面模式

3.2 Tomcat 中大量使用了門面模式。

Tomcat 中有很多不同組件,每個組件要相互交互數據,用門面模式隔離數據是個很好的方法。在Tomcat源碼中搜索Facade(門面):

從源碼角度理解Java設計模式——門面模式

其中拿RequestFacade.class來說,它是HttpServletRequest外觀類,裡面封裝了各種操作request的常見方法,比如getParameter方法等。

Request.class中封裝了 HttpRequest 接口能夠提供的數據,是子系統的門面。實際項目中對request進行操作的時候,其實使用的都是RequestFacade這個外觀類對象:

從源碼角度理解Java設計模式——門面模式

門面模式是一個很好的封裝方法,一個子系統比較複雜時,比如算法或者業務比較複雜,就可以封裝出一個或多個門面出來,項目的結構簡單,而且擴展性非常好。

門面模式提供了外界對子系統的訪問黑箱操作,無論內部怎麼變化,對外部訪問者來說,還是同一個門面,同一個方法。

參考:

設計模式 | 外觀模式及典型應用


分享到:


相關文章: