上一篇《python設計模式-適配器模式》介紹瞭如何將一個類的接口轉換成另外一個符合指望的接口。這一篇將要介紹須要一個爲了簡化接口而改變接口的新模式-外觀模式(Facade-Pattern)。python
問題
:若是你組裝了一套家庭影院,內含播放器、投影機、自動屏幕、立體聲音響、爆米花機等。如何設計一個遙控器,能夠簡單的操做這個系統中的各個組件呢?
首先來看一下最笨方式觀賞電影的步驟:小程序
寫成類和方法的調用大概是如下的樣子:設計模式
# 打開爆米花機,開始爆米花 poper.on() poper.pop() # 燈光調暗 lights.dim(10) # 放下屏幕 screen.down() # 打開投影儀,設置爲寬屏模式 projector.on() projector.setInput(dvd) projector.wideScreenMode() # 打開功放 設置爲DVD 調整成環繞立體聲模式,音量調到5 amp.on() amp.setDvd(dvd) amp.setSurroundSound() amp.setVolume(5) # 打開dvd 播放器 dvd.on() dvd.play(movie)
能夠看到代碼中涉及到6個不一樣的類,並且電影看完後還須要回退,一切都要再反着重來一遍。怎樣簡化一下操做呢?
如今,外觀模式就能夠大展身手了。併發
使用外觀模式,能夠經過實現一個提供更合理的接口的外觀類,將子系統變得更容易使用。固然,原來的接口還在。
先來看一下外觀模式如何運做ide
HomeTheaterFacade
,這個類暴露出來幾個簡單的方法,好比watchMovie
,endMovie
。watchMovie
方法。
注意:
spa
- 能夠有多個外觀
- 外觀提供簡化的接口,但不隔離子系統
- 外觀將實現從子系統中解耦,好比:如今有個子系統的組件須要升級換代,只須要把外觀代碼作相應的修改就能夠實現
- 外觀和適配器均可以包裝多個類,可是
外觀的意圖時簡化接口的調用
,而適配器的意圖是將接口轉換成不一樣的接口
。
class HomeTheaterFacade(object): #先聲明須要用的子組件 amp = Amplifier() tuner = Tuner() dvd = DvdPlayer() cd = CdPlayer() projector = Projector() lights = TheaterLights() screen = Screen() popper = PopcornPopper() def watchMovie(self, movie): # watchMovie 將以前須要手動處理的任務批量處理 print("Get ready to watch a movie...") # 打開爆米花機,開始爆米花 self.poper.on() self.poper.pop() # 燈光調暗 self.lights.dim(10) # 放下屏幕 self.screen.down() # 打開投影儀,設置爲寬屏模式 self.projector.on() self.projector.setInput(dvd) self.projector.wideScreenMode() # 打開功放 設置爲DVD 調整成環繞立體聲模式,音量調到5 self.amp.on() self.amp.setDvd(dvd) self.amp.setSurroundSound() self.amp.setVolume(5) # 打開dvd 播放器 self.dvd.on() self.dvd.play(movie) def endMovie(self): # endMovie 負責關閉一切,由子系統中的組件完成 print("Shutting movie theater down...") self.popper.off() self.lights.on() self.screen.up() self.projector.off() self.amp.off() self.dvd.stop() self.dvd.eject() self.dvd.off()
def main(): home_theater = HomeTheaterFacade() # 實例化外觀 home_theater.watchMovice() # 使用簡化方法開啓 關閉電影ß home_theater.endMovice()
定義:
外觀模式提供了一個統一的接口,用來訪問子系統中的一羣接口。外觀定義了一個高層接口,讓子系統更容易使用。
從類圖也能夠了解到,外觀模式的主要意圖是提供一個更簡單易用的接口。設計
最少知識原則
的意思是減小對象之間的交互,只和幾個特定的對象交互。code
這個原則是但願在設計中,不要耦合太多的類,以避免修改系統時,會影響到其它部分。
好比:若是想從DVD播放器獲取音響的音量,能夠在Dvd播放器中加入一個方法,用來像音響請求當前音量,而不是先返回音響對象,再從音響對象返回音量。協程
# 很差的實踐 def get_volume(): tuner = dvd.tuner() return tuner.get_volume # 好的實踐 def get_volume(): # 這裏要給dvd 對象加一個get_volume方法 return dvd.get_volume
缺點:
雖然這個原則減小了對象之間的依賴,可是也會致使更多的包裝被製造出來(好比上邊例子中,就須要給dvd 加一個 get_volume
方法),這也可能會致使系統更復雜。
再回顧一下外觀模式的例子,會發現外觀模式符合最少知識原則
,客戶端只有HomeTheaterFacade
這一個交互對象。它的存在讓系統調用變的更簡單,而且若是須要子系統有模塊須要升級,只須要修改HomeTheaterFacade
這個類就能夠完成升級。對象
本文例子來自《Head First 設計模式》。
最後,感謝女友支持和包容,比❤️
也能夠在公號輸入如下關鍵字獲取歷史文章:公號&小程序
| 設計模式
| 併發&協程