裝飾模式用於動態地給一個對象添加一些額外的職責,它可以理解爲繼承的替代方案。就增加功能來說,裝飾模式比生成子類更加靈活。
比如一家奶茶店,店裏的奶茶可以加各種配料,這時應該怎麼實現呢?
一種方案是先構造一個奶茶抽象類,然後生成各種子類如珍珠奶茶、紅豆奶茶、椰果奶茶 ...... ,但事實上一杯奶茶奶茶裏可以添加多種配料,比如珍珠野果奶茶,如果店裏的配料很多,排列組合之後要生成的子類就更多了,所以繼承對於這個問題不是一個好的解決方案。
這時就可以採用裝飾者模式。定義一個奶茶接口 TeaWithMilk 、定義一個Decorator 抽象類(該類實現了TeaWithMilk,同時將設置TeaWithMilk 爲可以被繼承的成員變量,同時定義一個setTeaWithMilk函數或在構造函數中設置該成員變量),珍珠奶茶、紅豆奶茶等作爲 Decoreater 的子類,重寫setTeaWithMilk函數。實例化一個奶茶對象(該對象應實現TeaWithMilk)。這時就可以將奶茶對象作爲參數傳遞給珍珠奶茶等子類的實例,想要再加入椰果時,就將珍珠奶茶的實例傳入椰果奶茶的實例。
裝飾者模式的結構如下:
主要角色爲:
抽象構件(Component)角色:給出一個抽象接口,已規範準備接收附加責任的對象。、
具體構件(ConcreteComponent)角色:定義一個將要接收附加責任的類
裝飾(Decorator)角色:持有一個構件(Component)對象的實例,並定義一個與抽象構件接口一致的接口。
具體裝飾(ConcreteDecorator)角色:負責給構件對象“貼上”附加的責任
裝飾模式利用 SetComponent 函數或 構造函數 對對象進行包裝;
使用裝飾模式,意味着每個裝飾對象的實現與如何使用這個對象就分開了,每個對象只需要關心自己的功能,不需要關心自己要被怎樣添加到裝飾鏈中。或者說可以把類中的裝飾功能從類中去除,簡化原有的類;可以有效區分類的核心功能和和裝飾功能,且去除相關代碼中的重複邏輯。
在實際操作中,如果只有一個concreteComponent類,可以將其與Component類合併,讓Decorater類繼承concreteComponent類;如果只有一個ConcreateDecorate類,也可以將其與Decorater類合併。