裝飾者模式

2021-08-15 18:54:32 字數 2093 閱讀 1016

在談裝飾這模式之前,我想讓大家思考一下,我們開發的時候為什麼要遵守開閉原則(對拓展開放,對修改關閉)?這看起來是乙個非常矛盾的事情,又要拓展功能,又不能夠修改已有的**。其實,這樣做最主要的原因是防止因為修改已有**引入新的bug,已有的**一般都是經過檢測的,很少有bug,如果直接在上面修改的話,很可能導致未知的錯誤,可能引起別的元件的故障,甚至癱瘓整個系統。

在明白上述這一點之後,我們就比較容易理解那些明明兩三行**就能完成的功能,為什麼要在上面做各種抽象了,主要是為了三個方面:

**重用(從更長遠的角度看起來,簡化開發)

易於拓展(增加功能方便)

便於維護(不修改已有**,結構層次清晰)

ok,下面進入正題

我們假設以下情景:有一家diy奶茶廠商,要管理很多飲品,不同的配方就是一種產品,假設主料有茶,咖啡等等,配料有紅豆,糖,牛奶,等等,我們要科學的對這些材料進行管理,按照物件導向的思維,每一種產品就是乙個類,我的天,無數的組合豈不是無窮無盡的類,這樣設計顯然是不科學的。我們這時候可以用裝飾者模式,我們看看裝飾者模式是如何做的

我們先來觀察這些產品有何特點:都是由主料和多種輔料復合而成的,這時候我們就要想辦法,如何動態的去給主料裡新增輔料,而不是在編譯的時候直接寫死

先上類圖

我們把主料和輔料裝飾者都實現beverage介面,這樣做的作用最後再說。下面我們來看看**

public

inte***ce beverage

奶茶的**和咖啡一樣,我就不重複了

public

class

coffee

implements

beverage

public

float

cost()

}

//抽象方法,啥也沒做

public

abstract

class

ingredientsdecorator

implements

beverage

下面幾個輔料的方法也幾乎一致,我就只寫乙個了

public

class

pudding

extends

ingredientsdecorator

//增強描述功能

public string discription()

//增強付款功能

public

float

cost()

}

我們寫個測試**

public

static

void

main(string args)

輸出:6.0

咖啡,冰,糖

我們來看看之前留下的問題,為什麼要裝飾者要實現beverage類?

public

pudding(beverage beverage)

看看這個**,其實就是為了這段**,裝飾物件可以不斷的被裝飾,也就實現了加各種輔料

這裡說一下繼承,繼承不僅僅是為了**重用,還有乙個作用就是保持型別的一致,我們裝飾者模式主要就是利用了後面這一點

我們可以看到,用這種diy組合的方式就能達到我們的需求,就不用寫那麼多的類了

但是裝飾者模式也有不少的缺點:

可能裝飾類會非常多

如果被裝飾物件經過多次裝飾,可能會導致結構非常複雜

如果需要的物件需要進過多次裝飾,那麼人為的去組裝是非常難以保證正確性的

其實對於複雜的裝飾,我們一般會採用工廠模式去進行裝飾,這樣就不必去關注這些實現細節了

裝飾者模式是一種非常常見的模式,他能在不修改源**的情況下,動態的給原物件賦予新的功能,最常見的io類就大量使用了裝飾者模式

ps:原始碼位址

裝飾者模式

裝飾者模式 動態地將責任附加到物件上。若要擴張功能,裝飾者提供了比繼承更有彈性的替代方案。裝飾者可以在所委託被裝飾者的行為之前或之後,加上自己的行為,以達到特定的目的。裝飾者與被裝飾者物件具有相同的超型別。include include using namespace std class bever...

裝飾者模式

裝飾者模式,是在不改變原類檔案和使用繼承的情況下,動態地擴充套件乙個物件的功能。它是通過建立乙個包裝物件,也就是裝飾來包裹真實的物件。裝飾者模式中的角色 1 被裝飾者抽象component,是乙個介面或抽象類,就是定義最核心的物件,也是最原始的物件,這個類是需要裝飾類的基類。2 被裝飾者具體實現co...

裝飾者模式

裝飾者模式 裝飾者模式的好處是便於擴充套件,對乙個東西不管怎麼變,只需要找到相應的元件去改變它 1.如何組裝在一起 建立主題 packetbodycreator body new packetbodycreator 建立header packethtmlheadercreator html new ...