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