一、門面模式介紹
門面模式定義:也叫外觀模式,定義了一個訪問子系統的接口,除了這個接口以外,不允許其他訪問子系統的行為發生。
適用場景:子系統很複雜時,增加一個接口供外部訪問。
優點:簡化層級間的調用,減少依賴,防止風險。
缺點:如果設計不當,增加新的子系統可能需要修改門面類的源代碼,違背了開閉原則。
類型:結構型。
類圖:
![從源碼角度理解Java設計模式——門面模式](http://p2.ttnews.xyz/loading.gif)
二、門面模式簡單實例
小明想開一個餐館,要去政府部門辦理衛生許可證、辦理稅務登記和辦理工商登記,以前小王要一一親自去辦理,這不是一件容易的事。
政府最近簡化了政務辦理流程,只用小明訪問一次簡化政務辦理的門面就可以辦理到全部證件。
![從源碼角度理解Java設計模式——門面模式](http://p2.ttnews.xyz/loading.gif)
測試一下:
三、日誌門面
阿里巴巴開發手冊中有這樣一條規定:
其中Log4j、Logback都是日誌框架,它們都有著自己的獨立的Api接口。如果單獨使用某個框架,會大大增加系統的耦合性。而SLF4J並不是真正的日誌框架,它有一套通用的API接口。
所以阿里開發手冊中直接強制用SLF4J日誌門面,日誌門面是門面模式的一個典型應用。SLF4J的helloworld如下:
進入info方法:
上圖的SubstituteLogger.class裡還是調用Logger接口的info方法,NOPLogger如同它的名字一樣:什麼都不做,所以只有在系統引入Logback這個日誌框架時,才有了Logger真正的實現類。那Log4j、Logback等日誌框架是怎麼和SLF4J對接的?
任何日誌框架,一定都是通過自己的StaticLoggerBinder類來和SLF4J對接:
這個類的實現,在不同的框架中,實現不同,以Logback為例:
這個實現的類被設計為或者簡單的返回一個默認的LoggerContext(LoggerContext是ILoggerFactory在logback中的實現),或者通過ContextSelector(logback特有的)來選擇一個LoggerContext並返回。
四、源碼中的門面模式
3.1 Spring JDBC中的JdbcUtils對原生的JDBC進行封裝,讓調用者統一訪問。
3.2 Tomcat 中大量使用了門面模式。
Tomcat 中有很多不同組件,每個組件要相互交互數據,用門面模式隔離數據是個很好的方法。在Tomcat源碼中搜索Facade(門面):
其中拿RequestFacade.class來說,它是HttpServletRequest外觀類,裡面封裝了各種操作request的常見方法,比如getParameter方法等。
Request.class中封裝了 HttpRequest 接口能夠提供的數據,是子系統的門面。實際項目中對request進行操作的時候,其實使用的都是RequestFacade這個外觀類對象:
門面模式是一個很好的封裝方法,一個子系統比較複雜時,比如算法或者業務比較複雜,就可以封裝出一個或多個門面出來,項目的結構簡單,而且擴展性非常好。
門面模式提供了外界對子系統的訪問黑箱操作,無論內部怎麼變化,對外部訪問者來說,還是同一個門面,同一個方法。
參考:
設計模式 | 外觀模式及典型應用
閱讀更多 Java是最好的語言NO1 的文章