成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Go學設計模式--裝飾器和職責鏈,哪個模式實現中間件更科學?

開發 前端
裝飾器模式有不少優點,它是繼承的有力補充,比繼承靈活,在不改變原有對象的情況下,動態地給一個對象擴展功能,即插即用。通過使用不同裝飾類及這些裝飾類的排列組合,可以實現不同效果,完全遵循程序設計的“開閉原則”。

大家好,我是每周在這里陪你進步的網管~,本次我們繼續填坑,說一下裝飾器模式。

上篇文章我們說過裝飾器是代理模式的特殊應用,而且很多人說中間件是用裝飾器模式實現的,有的人說是用職責鏈實現的,那么這篇文章我們就來一起看看他們的異同。

什么是裝飾器

裝飾器模式(Decorator Pattern)也叫作包裝器模式(Wrapper Pattern),指在不改變原有對象的基礎上,動態地給一個對象添加一些額外的職責。就增加功能來說,裝飾器模式相比生成子類更為靈活,屬于結構型設計模式。

給對象添加新行為最簡單直觀的辦法就是擴展本體對象,通過繼承的方式達到目的。但是使用繼承不可避免地有如下兩個弊端:

繼承是靜態的,在編譯期間就已經確定,無法在運行時改變對象的行為。

子類只能有一個父類,當需要添加的新功能太多時,容易導致類的數量劇增。

而使用裝飾器模式,我們通過將現有對象放置在實現了相同一套接口的包裝器對象中來動態地向現有對象添加新行為。在包裝器中進行我們代碼的擴展,有助于重用功能并且不會修改現有對象的代碼,符合“開閉原則”。

這里被放置在包裝對象的“現有對象”通常會被叫做“組件”(Component),而包裝組件的包裝器對象就是我們常說的“裝飾器”(Decorator),因為裝飾器會組件實現相同接口,故客戶端無法識別兩者的差異,也就不需要在增加裝飾器時對客戶端調用代碼進行修改了。

從上面關于裝飾器模式的描述中 ,會感覺他跟代理模式很像。這是因為他們本來在結構上也幾乎一樣,裝飾器算是代理的一個特殊應用--裝飾器模式的一個特點是可以嵌套多層裝飾器,相當于給代理再加代理。不過代理強調的是對本體對象的訪問控制,而裝飾器是用來對本地進行增強,兩者在使用目的上不一樣。

上面裝飾器模式的用處特點用文字描述了這么多,下面我們用 UML 類圖展示一下它的結構,讓我們在寫代碼前對模式中的各個角色有個更清晰的認識。

裝飾器的結構

用 UML 類圖表示裝飾器模式的結構如下:

圖片

從圖中可以看到裝飾器模式中主要有如下幾個角色:

  • 客戶端:會用多層裝飾器來封裝組件, 最后調用裝飾好的包裝器的方法,啟動執行。
  • 組件接口:Component聲明裝飾器對象和被裝飾的組件對象要實現的公用接口。
  • 組件實現:具體的組件實現類它的Operation方法中定義了組件的基礎行為, 裝飾類可以增強這些行為。
  • 基礎裝飾類:擁有一個指向被封裝對象的成員變量。 在自己的Operation?方法中調用被裝飾對象的Operation方法
  • 具體裝飾類:重寫父類的Operation?方法實現增強邏輯。類圖里已經給出了要實現的主要邏輯,第四步的基礎裝飾類并不需要一定存在,完全可以由具體裝飾類來持有對被裝飾對象的引用,并實現增強邏輯,這樣一來整體的結構會更簡單一些。

注意:圖中的方法名在代碼實現里可自己定義,不需要完全跟圖里給出的方法名一樣。

我們可以跟上節代理模式的UML類圖做個對比,兩者在結構上非常相似,尤其是省略了BaseDecorator這一層后,在結構上基本上是一摸一樣,這樣我們一直再強調的--"裝飾器是代理模式的特殊應用"的一個論據。

下面我們看一下實現裝飾器模式的代碼模版,本文中提供了Go語言實現一個簡單裝飾器模式的代碼模版。

裝飾器模式代碼實現

清楚了裝飾器模式結構的組成后,再來寫代碼就會清晰很多,接下來我們演示一下用裝飾器模式實現增強游戲主機的一個例子。

首先我們定義一個游戲主機的產品接口,它就是上面類圖中組件和裝飾器的公共接口。

// PS5 產品接口
type PS5 interface {
StartGPUEngine()
GetPrice() int64
}

然后我們提供一個基礎的產品實現類作為裝飾器模式中的組件。

// CD 版 PS5主機
"本文使用的完整可運行源碼
去公眾號「網管叨bi叨」發送【設計模式】即可領取"
type PS5WithCD struct{}

func (p PS5WithCD) StartGPUEngine() {
fmt.Println("start engine")
}
func (p PS5WithCD) GetPrice() int64 {
return 5000
}

這里給出的是一個 CD 版的游戲主機,平時玩游戲的同學都會知道,一般還會有數字版的主機,價格會便宜點,這種情況我們可以提供一個數字版游戲主機的實現作為組件實現類。

// PS5 數字版主機
type PS5WithDigital struct{}

func (p PS5WithDigital) StartGPUEngine() {
fmt.Println("start normal gpu engine")
}

func (p PS5WithDigital) GetPrice() int64 {
return 3600
}

那么除了這兩種基礎的產品類型,廠商一般還會開發各種主題限定配色的主機、增加了硬件配置的主機等等,這兩種在價格上肯定會跟基礎版有些不一樣,針對這種層面的擴展我們可以使用裝飾器來實現,避免對基礎組件類的更改。

下面是用兩個裝飾器實現的Plus版和主題配色版的兩個增強。

"本文使用的完整可運行源碼
去公眾號「網管叨bi叨」發送【設計模式】即可領取"
// 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
}

根據裝飾器模式的特點,兩個增強還可以疊加在一起,組合出即高配主題限定版主機...... 呃,是不是有點某游戲大廠每年發新機時給你的感覺了,就是不出第二代,每年給你多發幾個限定配色、升級下屏幕,說的就是你 XXX(各位自己評論里腦補一下)

好了,在客戶端我們把裝飾器和組件組合起來就能獲得一款高配主題限定版主機......

"本文使用的完整可運行源碼
去公眾號「網管叨bi叨」發送【設計模式】即可領取"
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)
}

本文的完整源碼,已經同步收錄到我整理的電子教程里啦,可向我的公眾號「網管叨bi叨」發送關鍵字【設計模式】領取。

圖片

裝飾器和幾個模式的區別

裝飾器和代理在結構上類似,在行為上跟職責鏈模式類似,現在我們總結一下他們之間的區別

裝飾器模式 VS 代理模式

  • 裝飾器模式就是代理模式的一個特殊應用。
  • 裝飾器模式強調自身功能的擴展。
  • 代理模式強調對代理過程的控制。

裝飾器 VS 職責鏈模式

裝飾器和職責鏈在行為上看都是多個單元進行組合完成邏輯處理,但是裝飾器注重給某樣東西添加擴展,最終會得到一個產品。而職責鏈更強調分步驟完成某個流程,更像是一個任務鏈表,而且與裝飾器模式不同的是,職責鏈可以隨時終止。

舉個例子來說,針對OA系統請假審批這個場景,假設員工請假需要得到組長、總監和經理的批準才行。在這種情況下,使用裝飾器模式實現的話無論您的請假在前面的環節被批準還是被拒絕,整個鏈條都不會中斷,最終我們會得到三個級別審批人對申請的全部反饋。

而使用職責鏈模式的話,在每個階段,每個審批人都有權批準或拒絕。如果請求在任何級別被拒絕,那么整個流程就會結束,請求不會繼續流轉到下一個級別的審批人那里。

所以看到這里,你覺得像Web框架的中間件這種東西應該拿職責鏈還是裝飾器實現呢?

總結

裝飾器模式有不少優點,它是繼承的有力補充,比繼承靈活,在不改變原有對象的情況下,動態地給一個對象擴展功能,即插即用。通過使用不同裝飾類及這些裝飾類的排列組合,可以實現不同效果,完全遵循程序設計的“開閉原則”。

但裝飾器的使用必將會給程序帶來更高的復雜性,更低的可讀性,子類集成的代碼結構會更直白易懂一些,而且雖然裝飾器符合“開閉原則”,但是它會給程序帶來更多的類,動態裝飾在多層裝飾時會更復雜。

所以總體上使用裝飾器模式的時候也是兩害相較取其輕,為了不頻繁修改已經成型的子類而引入更多裝飾器類。

應用的時候一定要謹記裝飾器是“增強”某個事物用的,可千萬別把事物本身實現的主邏輯用裝飾器實現了。

責任編輯:武曉燕 來源: 網管叨bi叨
相關推薦

2011-10-24 07:41:38

SOA中間件應用服務器

2023-09-04 13:14:00

裝飾器設計模式

2015-12-21 14:56:12

Go語言Http網絡協議

2021-07-12 10:24:36

Go裝飾器代碼

2023-12-13 13:28:16

裝飾器模式Python設計模式

2023-05-15 08:51:46

解釋器模式定義

2022-01-19 08:21:12

設計裝飾器模式

2019-11-18 09:58:11

中間件投遞模式

2021-10-06 19:03:35

Go中間件Middleware

2022-10-28 13:33:05

Push模式互聯網高并發

2022-11-18 07:54:02

Go中間件項目

2024-02-23 12:11:53

裝飾器模式對象

2013-12-12 10:55:21

2022-09-21 08:47:05

項目多線程對象

2024-04-10 12:27:43

Python設計模式開發

2018-02-01 10:19:22

中間件服務器系統

2024-05-06 12:30:51

Go語言中間件

2025-03-13 09:22:39

2023-04-10 09:20:13

設計模式訪客模式

2023-05-04 08:47:31

命令模式抽象接口
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91在线电影 | 91看片免费| 久久久精品在线 | 给我免费的视频在线观看 | 精品国产不卡一区二区三区 | 少妇特黄a一区二区三区88av | 亚洲欧美日韩在线 | av 一区二区三区 | 97超碰在线免费 | 日韩一级 | 精品国产31久久久久久 | 视频一区二区中文字幕 | 久久精品一区二区三区四区 | 97久久超碰| 免费成人在线网 | 日韩精品四区 | 一区二区在线 | 五月婷亚洲 | 亚洲色图综合 | 91精品国产91久久久久久吃药 | 成人精品一区二区三区中文字幕 | 久久久久国产精品www | 国产四区| 日韩www | 亚洲精品亚洲人成人网 | 欧产日产国产精品国产 | 亚洲欧美中文日韩在线v日本 | 亚洲最大成人综合 | 亚洲人在线播放 | av黄色免费在线观看 | 2018国产精品 | 精品欧美一区二区三区久久久 | 91在线精品视频 | 久久性色 | 欧美成人精品在线 | 欧美成人精品一区二区男人看 | 成人在线日韩 | 香蕉久久久久久 | 天天拍天天操 | 日本电影韩国电影免费观看 | 久久在线 |