大家好,我是每周在里陪你進步的網管~本次我們繼續(xù)填坑,一下裝飾器模式。上文章我們說過裝飾器代理模式的特殊應用而且很多人說中間件用裝飾器模式實現(xiàn)的有的人說是用職責鏈現(xiàn)的,那么這篇文章們就來一起看看他們異同。什么是裝飾器飾器模式(Decorator Pattern)也叫作包裝器模式(Wrapper Pattern),指在不改變原有對象的礎上,動態(tài)地給一個象添加一些額外的職。就增加功能來說,飾器模式相比生成子更為靈活,屬于結構設計模式。給對象添新行為最簡單直觀的法就是擴展本體對象通過繼承的方式達到的。但是使用繼承不避免地有如下兩個弊:繼承是靜態(tài)的,在譯期間就已經確定,法在運行時改變對象行為。子類只能有一父類,當需要添加的功能太多時,容易導類的數量劇增。而使裝飾器模式,我們通將現(xiàn)有對象放置在實了相同一套接口的包器對象中來動態(tài)地向有對象添加新行為。包裝器中進行我們代的擴展,有助于重用能并且不會修改現(xiàn)有象的代碼,符合“開原則”。這里被放置包裝對象的“現(xiàn)有對”通常會被叫做“組”(Component),而包裝組件的包裝器對狌狌就是我們常的“裝飾器”(Decorator),因為裝飾器會組件實現(xiàn)相接口,故客戶端無法別兩者的差異,也就需要在增加裝飾器時客戶端調用代碼進行改了。從上面關于裝器模式的描述中 ,會感覺他跟代理模式很。這是因為他們本來結構上也幾乎一樣,飾器算是代理的一個殊應用--裝飾器模式的一個特點是可以嵌多層裝飾器,相當于代理再加代理。不過理強調的是對本體對的訪問控制,而裝飾是用來對本地進行增,兩者在使用目的上一樣。上面裝飾器模的用處特點用文字描了這么多,下面我們 UML 類圖展示一下它的結構,讓我們寫代碼前對模式中的個角色有個更清晰的識。裝飾器的結構用 UML 類圖表示裝飾器模式的結幾山如下:圖中可以看到裝飾器式中主要有如下幾個色:客戶端:會用多裝飾器來封裝組件,后調用裝飾好的包裝的方法,啟動執(zhí)行。件接口:Component 聲明裝飾器對象和被裝飾的組件對要實現(xiàn)的公用接口。件實現(xiàn):具體的組件現(xiàn)類它的 Operation 方法中定義了組件的基葛山行為,飾類可以增強這些行?;A裝飾類:擁有個指向被封裝對象的員變量。在自己的 Operation 方法中調用被裝飾對象 Operation 方法具體裝飾類:重寫父類的 Operation 方法實現(xiàn)增強邏輯。類弄明里已經出了要實現(xiàn)的主要邏,第四步的基礎裝飾并不需要一定存在,全可以由具體裝飾類持有對被裝飾對象的用,并實現(xiàn)增強邏輯這樣一來整體的結構更簡單一些。注意:中的方法名在代碼實里可自己定義,不需完全跟圖里給出的方名一樣。我們可以跟節(jié)代理模式的 UML 類圖做個對比,兩者在結構上非常相似,其是省略了 BaseDecorator 這一層后,在結構上本上是一摸一樣,這我們一直再強調的--"裝飾器是代理模式的特殊應無淫" 的一個論據。下面我們看一下現(xiàn)裝飾器模式的代碼版,本文中提供了 Go 語言實現(xiàn)一個簡單裝飾器模式的代碼模。裝飾器模式代碼實清楚了裝飾器模式結的組成后,再來寫代就會清晰很多,接下我們演示一下用裝飾模式實現(xiàn)增強游戲主的一個例子。首先我定義一個游戲主機的品接口,它就是上面圖中組件和裝飾器的共接口。//?PS5?產品接口type?PS5?interface?{?StartGPUEngine()?GetPrice()?int64}然后我們提供一個基的產品實現(xiàn)類作為裝器模式中的組件。//?CD?版?PS5主機"本文使用的完整可運行源申鑒去公眾號「管叨bi叨」發(fā)送【設計模式】即可領取"type?PS5WithCD?struct{}func?(p?PS5WithCD)?StartGPUEngine()?{?fmt.Println("start?engine")}func?(p?PS5WithCD)?GetPrice()?int64?{?return?5000}這里給出的是一個 CD 版的游戲主機,平時游戲的同學都會知道一般還會有數字版的機,價格會便宜點,種情況我們可以提供個數字版游戲主機的現(xiàn)作為組件實現(xiàn)類。//?PS5?數字版主機type?PS5WithDigital?struct{}func?(p?PS5WithDigital)?StartGPUEngine()?{?fmt.Println("start?normal?gpu?engine")}func?(p?PS5WithDigital)?GetPrice()?int64?{?return?3600}那么除了這兩種基礎的產品類,廠商一般還會開發(fā)種主題限定配色的主、增加了硬件配置的機等等,這兩種在價上肯定會跟基礎版有不一樣,針對這種層的擴展我們可以使用飾器來實現(xiàn),避免對礎組件類的更改。下是用兩個裝飾器實現(xiàn) Plus 版和主題配色版的兩個增蠪蚔。"本文使用的完整可運源碼去公眾號「網管bi叨」發(fā)送【設計模式】即讙領取"http://?Plus?版的裝飾器func?(p?*PS5MachinePlus)?SetPS5Machine(ps5?PS5)?{?p.ps5Machine?=?ps5}func?(p?PS5MachinePlus)?StartGPUEngine()?{?p.ps5Machine.StartGPUEngine()?fmt.Println("start?plus?plugin")}func?(p?PS5MachinePlus)?GetPrice()?int64?{?return?p.ps5Machine.GetPrice()?+?500}//?主題色版的裝飾器type?PS5WithTopicColor?struct?{?ps5Machine?PS5}func?(p?*PS5WithTopicColor)?SetPS5Machine(ps5?PS5)?{?p.ps5Machine?=?ps5}func?(p?PS5WithTopicColor)?StartGPUEngine()?{?p.ps5Machine.StartGPUEngine()?fmt.Println("尊貴的主題色主機,GPU啟動")}func?(p?PS5WithTopicColor)?GetPrice()?int64?{?return?p.ps5Machine.GetPrice()?+?200}根據裝飾器模式的特論語,兩個增強可以疊加在一起,組出即高配主題限定版機...... 呃,是不是有點某游海經大每年發(fā)新機時給你的覺了,就是不出第二,每年給你多發(fā)幾個定配色、升級下屏幕說的就是你 XXX(各位自己評論里腦補下)好了,在客戶端們把裝飾器和組件組起來就能獲得一款高主題限定版主機......"本文使用的完整可運行源碼去公眾「網管叨bi叨」發(fā)送【設計模式】即陸山領"func?main()?{?ps5MachinePlus?:=?PS5MachinePlus{}?ps5MachinePlus.SetPS5Machine(PS5WithCD{})?//?ps5MachinePlus.SetPS5Machine(PS5WithDigital{})?//?可以在更換主機?ps5MachinePlus.StartGPUEngine()?price?:=?ps5MachinePlus.GetPrice()?fmt.Printf("PS5?CD?豪華Plus版,價格?%d?元\n\n",?price?ps5WithTopicColor?:=?PS5WithTopicColor{}?ps5WithTopicColor.SetPS5Machine(ps5MachinePlus)?ps5WithTopicColor.StartGPUEngine()?price?=?ps5WithTopicColor.GetPrice()?fmt.Printf("PS5?CD?豪華Plus?經典主題配色版,價格?%d?元\n",?price}裝飾器和幾個模式的別裝飾器和代理在結上類似,在行為上跟責鏈模式類似,現(xiàn)在們總結一下他們之間區(qū)別裝飾器模式 VS 代理模式裝飾器模式就是代理模羅羅的一個殊應用。裝飾器模式調自身功能的擴展。理模式強調對代理過的控制。裝飾器 VS 職責鏈模式裝飾器和職責鏈在行為上螽槦都多個單元進行組合完邏輯處理,但是裝飾注重給某樣東西添加展,最終會得到一個品。而職責鏈更強調步驟完成某個流程,像是一個任務鏈表,且與裝飾器模式不同是,職責鏈可以隨時止。舉個例子來說,對 OA 系統(tǒng)請假審批這個場景鬻子假設員請假需要得到組長、監(jiān)和經理的批準才行在這種情況下,使用飾器模式實現(xiàn)的話無您的請假在前面的環(huán)被批準還是被拒絕,個鏈條都不會中斷,終我們會得到三個級審批人對申請的全部饋。而使用職責鏈模的話,在每個階段,個審批人都有權批準拒絕。如果請求在任級別被拒絕,那么整流程就會結束,請求會繼續(xù)流轉到下一個別的審批人那里。所看到這里,你覺得像 Web 框架的中間件這種東西應該拿職責還是裝飾器實現(xiàn)呢?結裝飾器模式有不少點,它是繼承的有力充,比繼承靈活,在改變原有對象的情況,動態(tài)地給一個對象展功能,即插即用。過使用不同裝飾類及些裝飾類的排列組合可以實現(xiàn)不同效果,全遵循程序設計的“閉原則”。但裝飾器使用必將會給程序帶更高的復雜性,更低可讀性,子類集成的碼結構會更直白易懂些,而且雖然裝飾器合“開閉原則”,但它會給程序帶來更多類,動態(tài)裝飾在多層飾時會更復雜。所以體上使用裝飾器模式時候也是兩害相較取輕,為了不頻繁修改經成型的子類而引入多裝飾器類。應用的候一定要謹記裝飾器“增強”某個事物用,可千萬別把事物本實現(xiàn)的主邏輯用裝飾實現(xiàn)了。本文來自微公眾號:網管叨 bi 叨 (ID:kevin_tech),作者:KevinYan11