摘要:上一篇設計模式適配器模式介紹了如何將一個類的接口轉換成另一個符合期望的接口。這一篇將要介紹需要一個為了簡化接口而改變接口的新模式外觀模式。
上一篇《python設計模式-適配器模式》介紹了如何將一個類的接口轉換成另一個符合期望的接口。這一篇將要介紹需要一個為了簡化接口而改變接口的新模式-外觀模式(Facade-Pattern)。
問題問題:如果你組裝了一套家庭影院,內含播放器、投影機、自動屏幕、立體聲音響、爆米花機等。如何設計一個遙控器,可以簡單的操作這個系統中的各個組件呢?
首先來看一下最笨方式觀賞電影的步驟:
打開爆米花機
開始爆米花
將燈光調暗
放下屏幕
打開投影儀
將投影機的輸入切換到播放器
將投影及設置在寬屏模式
打開功放
將功放的輸入設置為播放器
將攻防設置為環繞立體聲
將攻防音量調到適中
打開播放器
播放電影
寫成類和方法的調用大概是以下的樣子:
# 打開爆米花機,開始爆米花 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個不同的類,而且電影看完后還需要回退,一切都要再反著重來一遍。怎樣簡化一下操作呢?
現在,外觀模式就可以大展身手了。
使用外觀模式,可以通過實現一個提供更合理的接口的外觀類,將子系統變得更容易使用。當然,原來的接口還在。解決方法
先來看一下外觀模式如何運作
這里為家庭影院系統創建了一個新的外觀類HomeTheaterFacade,這個類暴露出來幾個簡單的方法,比如watchMovie,endMovie。
這個外觀類將家庭影院的多個組件看作一個子系統,通過調用這個子系統來實現watchMovie方法。
外觀只提供了一個更直接的操作方式,并沒有將原來的子系統隔離,子系統的功能還可以使用
示例注意:
可以有多個外觀
外觀提供簡化的接口,但不隔離子系統
外觀將實現從子系統中解耦,比如:現在有個子系統的組件需要升級換代,只需要把外觀代碼做相應的修改就可以實現
外觀和適配器都可以包裝多個類,但是外觀的意圖時簡化接口的調用,而適配器的意圖是將接口轉換成不同的接口。
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()定義
定義:外觀模式提供了一個統一的接口,用來訪問子系統中的一群接口。外觀定義了一個高層接口,讓子系統更容易使用。
從類圖也可以了解到,外觀模式的主要意圖是提供一個更簡單易用的接口。
最少知識原則(least Knowledge)最少知識原則的意思是減少對象之間的交互,只和幾個特定的對象交互。
這個原則是希望在設計中,不要耦合太多的類,以免修改系統時,會影響到其它部分。
比如:如果想從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 設計模式》。
最后,感謝女朋友支持和包容,比??
也可以在公號輸入以下關鍵字獲取歷史文章:公號&小程序 | 設計模式 | 并發&協程
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/42651.html
摘要:在本節實驗中,我們學習了四種設計模式策略模式,觀察者模式,命令模式以及模板方法模式。這四種設計模式都是行為型模式。這就是適配器模式。下面讓我們看看適配器模式在實驗樓中使用吧。準確來說,裝飾者模式能動態的給對象添加行為。 1、策略模式 策略模式將各種操作(算法)進行封裝,并使它們之間可以互換。互換的意思是說可以動態改變對象的操作方式(算法)。 -- coding: utf-8 -- im...
摘要:序列文章面試之函數面試之對象面試之數組的幾個不操作面試之對比分析面試之數據結構與算法前言設計模式如果應用到項目中,可以實現代碼的復用和解耦,提高代碼質量。 showImg(https://segmentfault.com/img/bVbq2VA?w=480&h=260); 序列文章 JS面試之函數(1)JS面試之對象(2)JS面試之數組的幾個不low操作(3)JS面試之http0.9~...
第1題: Python如何爬取 HTTPS 網站? 這類問題屬于簡單類問題 在使用 requests 前加入:requests.packages.urllib3.disable_warnings()。 為 requests 添加 verify=False 參數 導入ssl模塊 import ssl ssl._create_default_https_context = ssl....
第1題: Python如何爬取 HTTPS 網站? 這類問題屬于簡單類問題 在使用 requests 前加入:requests.packages.urllib3.disable_warnings()。 為 requests 添加 verify=False 參數 導入ssl模塊 import ssl ssl._create_default_https_context = ssl....
摘要:外觀設計模式外部與一個子系統的通信必須通過一個統一的門面對象進行,這就是門面模式。此角色知曉相關的子系統的功能和責任。外觀模式結構客戶端正常調用方式外觀模式調用方式實現未使用外觀模式子系統類客戶端調用使用外觀模式子系統類同上外觀類客戶端調用 外觀設計模式 外部與一個子系統的通信必須通過一個統一的門面(Facade)對象進行,這就是門面模式。外觀模式為子系統提供了統一的界面, 屏蔽了子類...
閱讀 1503·2021-11-22 09:34
閱讀 3320·2021-09-29 09:35
閱讀 562·2021-09-04 16:40
閱讀 2912·2019-08-30 15:53
閱讀 2582·2019-08-30 15:44
閱讀 2584·2019-08-30 14:10
閱讀 1328·2019-08-29 18:43
閱讀 2205·2019-08-29 13:26