摘要:上一篇設(shè)計模式適配器模式介紹了如何將一個類的接口轉(zhuǎn)換成另一個符合期望的接口。這一篇將要介紹需要一個為了簡化接口而改變接口的新模式外觀模式。
上一篇《python設(shè)計模式-適配器模式》介紹了如何將一個類的接口轉(zhuǎn)換成另一個符合期望的接口。這一篇將要介紹需要一個為了簡化接口而改變接口的新模式-外觀模式(Facade-Pattern)。
問題問題:如果你組裝了一套家庭影院,內(nèi)含播放器、投影機、自動屏幕、立體聲音響、爆米花機等。如何設(shè)計一個遙控器,可以簡單的操作這個系統(tǒng)中的各個組件呢?
首先來看一下最笨方式觀賞電影的步驟:
打開爆米花機
開始爆米花
將燈光調(diào)暗
放下屏幕
打開投影儀
將投影機的輸入切換到播放器
將投影及設(shè)置在寬屏模式
打開功放
將功放的輸入設(shè)置為播放器
將攻防設(shè)置為環(huán)繞立體聲
將攻防音量調(diào)到適中
打開播放器
播放電影
寫成類和方法的調(diào)用大概是以下的樣子:
# 打開爆米花機,開始爆米花 poper.on() poper.pop() # 燈光調(diào)暗 lights.dim(10) # 放下屏幕 screen.down() # 打開投影儀,設(shè)置為寬屏模式 projector.on() projector.setInput(dvd) projector.wideScreenMode() # 打開功放 設(shè)置為DVD 調(diào)整成環(huán)繞立體聲模式,音量調(diào)到5 amp.on() amp.setDvd(dvd) amp.setSurroundSound() amp.setVolume(5) # 打開dvd 播放器 dvd.on() dvd.play(movie)
可以看到代碼中涉及到6個不同的類,而且電影看完后還需要回退,一切都要再反著重來一遍。怎樣簡化一下操作呢?
現(xiàn)在,外觀模式就可以大展身手了。
使用外觀模式,可以通過實現(xiàn)一個提供更合理的接口的外觀類,將子系統(tǒng)變得更容易使用。當然,原來的接口還在。解決方法
先來看一下外觀模式如何運作
這里為家庭影院系統(tǒng)創(chuàng)建了一個新的外觀類HomeTheaterFacade,這個類暴露出來幾個簡單的方法,比如watchMovie,endMovie。
這個外觀類將家庭影院的多個組件看作一個子系統(tǒng),通過調(diào)用這個子系統(tǒng)來實現(xiàn)watchMovie方法。
外觀只提供了一個更直接的操作方式,并沒有將原來的子系統(tǒng)隔離,子系統(tǒng)的功能還可以使用
示例注意:
可以有多個外觀
外觀提供簡化的接口,但不隔離子系統(tǒng)
外觀將實現(xiàn)從子系統(tǒng)中解耦,比如:現(xiàn)在有個子系統(tǒng)的組件需要升級換代,只需要把外觀代碼做相應(yīng)的修改就可以實現(xiàn)
外觀和適配器都可以包裝多個類,但是外觀的意圖時簡化接口的調(diào)用,而適配器的意圖是將接口轉(zhuǎn)換成不同的接口。
class HomeTheaterFacade(object): #先聲明需要用的子組件 amp = Amplifier() tuner = Tuner() dvd = DvdPlayer() cd = CdPlayer() projector = Projector() lights = TheaterLights() screen = Screen() popper = PopcornPopper() def watchMovie(self, movie): # watchMovie 將之前需要手動處理的任務(wù)批量處理 print("Get ready to watch a movie...") # 打開爆米花機,開始爆米花 self.poper.on() self.poper.pop() # 燈光調(diào)暗 self.lights.dim(10) # 放下屏幕 self.screen.down() # 打開投影儀,設(shè)置為寬屏模式 self.projector.on() self.projector.setInput(dvd) self.projector.wideScreenMode() # 打開功放 設(shè)置為DVD 調(diào)整成環(huán)繞立體聲模式,音量調(diào)到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 負責(zé)關(guān)閉一切,由子系統(tǒng)中的組件完成 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() # 使用簡化方法開啟 關(guān)閉電影? home_theater.endMovice()定義
定義:外觀模式提供了一個統(tǒng)一的接口,用來訪問子系統(tǒng)中的一群接口。外觀定義了一個高層接口,讓子系統(tǒng)更容易使用。
從類圖也可以了解到,外觀模式的主要意圖是提供一個更簡單易用的接口。
最少知識原則(least Knowledge)最少知識原則的意思是減少對象之間的交互,只和幾個特定的對象交互。
這個原則是希望在設(shè)計中,不要耦合太多的類,以免修改系統(tǒng)時,會影響到其它部分。
比如:如果想從DVD播放器獲取音響的音量,可以在Dvd播放器中加入一個方法,用來像音響請求當前音量,而不是先返回音響對象,再從音響對象返回音量。
# 不好的實踐 def get_volume(): tuner = dvd.tuner() return tuner.get_volume # 好的實踐 def get_volume(): # 這里要給dvd 對象加一個get_volume方法 return dvd.get_volume
缺點:雖然這個原則減少了對象之間的依賴,但是也會導(dǎo)致更多的包裝被制造出來(比如上邊例子中,就需要給dvd 加一個 get_volume方法),這也可能會導(dǎo)致系統(tǒng)更復(fù)雜。
再回顧一下外觀模式的例子,會發(fā)現(xiàn)外觀模式符合最少知識原則,客戶端只有HomeTheaterFacade這一個交互對象。它的存在讓系統(tǒng)調(diào)用變的更簡單,并且如果需要子系統(tǒng)有模塊需要升級,只需要修改HomeTheaterFacade這個類就可以完成升級。
本文例子來自《Head First 設(shè)計模式》。
最后,感謝女朋友支持和包容,比??
也可以在公號輸入以下關(guān)鍵字獲取歷史文章:公號&小程序 | 設(shè)計模式 | 并發(fā)&協(xié)程
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/42651.html
摘要:在本節(jié)實驗中,我們學(xué)習(xí)了四種設(shè)計模式策略模式,觀察者模式,命令模式以及模板方法模式。這四種設(shè)計模式都是行為型模式。這就是適配器模式。下面讓我們看看適配器模式在實驗樓中使用吧。準確來說,裝飾者模式能動態(tài)的給對象添加行為。 1、策略模式 策略模式將各種操作(算法)進行封裝,并使它們之間可以互換。互換的意思是說可以動態(tài)改變對象的操作方式(算法)。 -- coding: utf-8 -- im...
摘要:序列文章面試之函數(shù)面試之對象面試之數(shù)組的幾個不操作面試之對比分析面試之數(shù)據(jù)結(jié)構(gòu)與算法前言設(shè)計模式如果應(yīng)用到項目中,可以實現(xiàn)代碼的復(fù)用和解耦,提高代碼質(zhì)量。 showImg(https://segmentfault.com/img/bVbq2VA?w=480&h=260); 序列文章 JS面試之函數(shù)(1)JS面試之對象(2)JS面試之數(shù)組的幾個不low操作(3)JS面試之http0.9~...
第1題: Python如何爬取 HTTPS 網(wǎng)站? 這類問題屬于簡單類問題 在使用 requests 前加入:requests.packages.urllib3.disable_warnings()。 為 requests 添加 verify=False 參數(shù) 導(dǎo)入ssl模塊 import ssl ssl._create_default_https_context = ssl....
第1題: Python如何爬取 HTTPS 網(wǎng)站? 這類問題屬于簡單類問題 在使用 requests 前加入:requests.packages.urllib3.disable_warnings()。 為 requests 添加 verify=False 參數(shù) 導(dǎo)入ssl模塊 import ssl ssl._create_default_https_context = ssl....
摘要:外觀設(shè)計模式外部與一個子系統(tǒng)的通信必須通過一個統(tǒng)一的門面對象進行,這就是門面模式。此角色知曉相關(guān)的子系統(tǒng)的功能和責(zé)任。外觀模式結(jié)構(gòu)客戶端正常調(diào)用方式外觀模式調(diào)用方式實現(xiàn)未使用外觀模式子系統(tǒng)類客戶端調(diào)用使用外觀模式子系統(tǒng)類同上外觀類客戶端調(diào)用 外觀設(shè)計模式 外部與一個子系統(tǒng)的通信必須通過一個統(tǒng)一的門面(Facade)對象進行,這就是門面模式。外觀模式為子系統(tǒng)提供了統(tǒng)一的界面, 屏蔽了子類...
閱讀 1763·2021-11-22 09:34
閱讀 3418·2021-09-29 09:35
閱讀 645·2021-09-04 16:40
閱讀 2973·2019-08-30 15:53
閱讀 2645·2019-08-30 15:44
閱讀 2648·2019-08-30 14:10
閱讀 1389·2019-08-29 18:43
閱讀 2264·2019-08-29 13:26