外觀模式,一個每天都在用,卻被多數人在面試中忽視的模式
大家好,這里是每周都在陪你一起進步的網管~!今天繼續設計模式學習之旅,這次咱們分享個大家每個人在寫代碼時都用過,但面試時經常忽視它的設計模式--外觀模式,我們一起來看看吧。
現代的軟件系統都非常復雜,盡管我們已經想盡一切方法將其“分而治之”,把一個系統劃分為好幾個較小的子系統了,但是仍然可能會存在這樣的問題:子系統內有非常多的類,客戶端往往需要和許多對象打交道之后才能完成想要完成的功能。
模式的由來
在我們的生活中醫院就是這樣的。一般的醫院都會分為掛號、門診、化驗、收費、取藥等??床〉牟∪艘胫魏米约旱牟。ㄏ喈斢谝粋€客戶端想要實現自己的功能)就要和醫院的各個部門打交道。首先,病人需要掛號,然后門診,如果醫生要求化驗的話,病人就要去化驗,然后再回到門診室,最后拿藥,經過一系列復雜的過程后才能完成看病的過程。如下圖所示:
如果我們在醫院設立一個接待員的話,病人只負責和接待員接觸,由接待員負責與醫院的各個部門打交道,如下圖所示:
醫院設立的接待員的角色就是我們今天要介紹的外觀模式,系統通過引入外觀模式讓需要調用多個子系統各自部分的功能接口以完成的需求,變為調用方只需要跟外觀提供的統一功能進行交互即可。
引入外觀模式帶來的變化
模式定義
外觀模式又稱為門面模式,它是一種結構型模式。引入外觀模式后調用方與多個子系統的通信必須通過一個統一的外觀對象進行,外觀模式為子系統中的功能接口提供一個一致的界面,此模式定義了一個高層接口,這個接口使得這些子系統更加容易使用。
外觀模式的結構
外觀模式的結構其實很簡單,用一個UML圖就能描述清楚外觀模式里擁有哪些角色以及它們各自的特點,下面我們看一下外觀模式的類結構。
外觀模式編程實現
下面我們用Go代碼實現一個外觀模式。
這個例子里我們把電腦擁有的CPU、RAM內存和硬盤視為子系統,調用方想啟動電腦就得分別啟動這三個子系統才行,所以我們在子系統上增加一個外觀對象,讓調用方直接調用外觀對象,由外觀對象再去分別對接子系統最終完成電腦的啟動。
該實例源代碼引用自:https://github.com/yksz/go-design-patterns/blob/master/structure/facade.go
本文的完整源碼,已經同步收錄到我整理的電子教程里啦,可向我的公眾號「網管叨bi叨」發送關鍵字【設計模式】領取。
公眾號「網管叨bi叨」發送關鍵字【設計模式】領取。
使用外觀模式的知名庫
要說外觀模式在實際開發中的應用,首先讓我想起來的就是Java 里的Slf4j,它是一個抽象層,讓用戶對日志的操作統一由Slf4j跟用戶去對接,用戶用這個抽象層的API來寫日志, 底層具體用什么日志工具實現用戶完全不用關心,由Slf4j來對接Log4j、LogBack 這些日志工具,這樣就可以更方便地移植了。
這個抽象層 Slf4j 就是Simple logging Facade For Java 的簡稱,從名字里我們也能看出來,它是一個外觀模式的實踐應用,由于普及度很高,很多講解外觀模式的教程里都會提及它,拿它的實現來給讀者做分析。
總結
外觀模式的優點
- 簡化了調用過程,不用深入了解子系統,以防給子系統帶來風險。
- 減少系統依賴,松散耦合。
- 更好地劃分訪問層次,提高了安全性。
- 遵循迪米特法則
外觀模式的缺點
- 當增加子系統和擴展子系統行為時,需要對外觀進行重復更改,不符合開閉原則,可能容易帶來未知風險。