在談裝飾這模式之前,我想讓大家思考一下,我們開發的時候為什麼要遵守開閉原則(對拓展開放,對修改關閉)?這看起來是乙個非常矛盾的事情,又要拓展功能,又不能夠修改已有的**。其實,這樣做最主要的原因是防止因為修改已有**引入新的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 ...