標簽: 設計模式初涉
描述性文字
還記得工廠方法模式小豬開的奶茶店嗎?在那一節中講解的是
通過工廠方法模式來做奶茶,做奶茶的工作都已經交給小弟了,
小豬的工作量少了很多,剩下的就是敲起二郎腿坐著收錢了,
于是乎列了一張單子,寫出所有飲品的價格:
奶茶:
- 原味奶茶:5塊
- 珍珠奶茶:7塊
- 椰果奶茶:7塊
- 珍珠椰果奶茶:9塊
檸檬茶:
- 原味檸檬茶:3塊
- 金桔檸檬茶:5塊
然后顧客要什么點什么,按著菜單收費就好了,然而用戶的
需求都是多變的,他們覺得配料那里可以加點紅豆,然后你
的菜單需要新增:
- 紅豆奶茶:7塊
- 紅豆珍珠奶茶:9塊
- 紅豆椰果奶茶:9塊
- 紅豆珍珠椰果奶茶:11塊
食客又說,還可以加點其他的配料啊,黑鉆,果凍,涼粉,奶蓋,
燒仙草等,然后你的菜單就爆炸了,奶蓋果凍黑鉆燒仙草珍珠椰果奶茶,
2333,你仿佛特意在逗我笑,

每個組合都寫一個,這他么得寫多少個,而且用戶總是

每多一種配料,就得增加一堆飲品,玩毛。
我們必須想一個更優的套路,這個時候可以考慮引入裝飾者模式,
簡單來說就是:一層套一層,比如說要椰果珍珠奶茶:
奶茶 --> 套一層珍珠 --> 珍珠(奶茶) --> 套一層椰果 --> 椰果(珍珠(奶茶))
逼逼那么多,代碼演示下吧!
代碼實現
先定義一個抽象茶的父類,定義茶的名字與定義價格的抽象方法

接著定義配料的抽象類,所有配料都來繼承這個東東

好的,接著定義基本茶品,奶茶和檸檬茶


接著是各種配料,珍珠,椰果,紅豆,金桔,都是繼承配料類




接著開始自由搭配了:

打單:

可以,沒毛病,如果你要奶蓋果凍黑鉆燒仙草珍珠椰果奶茶,也無壓力,
沒新增一個配料就建一個類而已,不用每次都去新建一堆類,然后又
去繼承。
模式要點
定義:
動態的給對象添加一些額外的職責,就增加功能來說,裝飾者
模式比起生成子類更加靈活!
四個角色:
-
Component:抽象組件,可以是接口或抽象類,具體組件與抽象裝飾類
的共同父類,聲明了在具體組件中實現的業務方法,可以使客戶端以一致的方式
處理未修飾對象與修飾后的對象,實現了客戶端的透明操作,比如這里的Tea類。 -
ConcreteComponent:具體組件,實現抽象組件中生命的方法,裝飾器
類可以給他增加額外的責任(方法),比如這里的MilkTea和LemonTea。 -
Decorator:抽象裝飾類,裝飾組件對象的,內部一定要有一個指向
組件對象的引用!!!通過該引用可以調用裝飾前構建對象的方法,并通過
其子類擴展該方法,已達到裝飾的目的,比如這里的Decorator類。 -
ConcreteDecorator:具體裝飾類,抽象裝飾類的具體實現,可以調用抽象
裝飾類中定義的方法,也可以新增新的方法來擴充對象的行為。
UML類圖

適用場景
裝飾者模式是以對客戶端透明的方式擴展對象的功能,是繼承關系的一種替代方案!
以下情況可以考慮是想用對象組合(組合與委托):
- 在不影響其他對象的情況下,以動態、透明的方式給單個對象添加職責;
- 處理那些可以撤消的職責;
- 當不能采用生成子類的方法進行擴充時:一種情況是,可能有大量獨立的擴展,
為支持每一種組合將產生大量的子類,使得子類數目呈爆炸性增長。另一種情況
可能是因為類定義被隱藏,或類定義不能用于生成子類;
優缺點
- 擴展對象功能,比繼承靈活,不會導致類個數急劇增加;
- 可以通過一種動態的方式在運行時選擇不同的具體裝飾類,從而實現不同的行為;
- 避免了高層次類有太多的特征,可以從一個最簡單的類慢慢給他添加功能;
- 會產生很多小裝飾者對象,會影響性能,過多使用該模式也會使程序變得復雜。
本節代碼:
https://github.com/coder-pig/DesignPatternsExample/tree/master/7.Decorator%20Pattern