動態地給乙個物件增加一些額外的職責,就增加物件的功能來說,裝飾模式比生成子類更為靈活。裝飾模式是一種物件結構模式。我們常常通過繼承的方式來對乙個既有的類進行功能新增,但繼承方式有顯著的侷限性,因為
例如在視窗控制項當中,要增加新的功能如增加滾動條,增加背景,通過繼承的方式來增加新的功能,有下面的解決方案。
可以看到在這個解決方案中,我們分別將scroll
和bckgnd
的功能實現了三遍。其根本原因是繼承是一種強耦合的關係,我們無法把bckgndtextbox
中的bckgnd
部分拿出來給listbox
使用。於是我們期待一種模式,可以像繼承這樣方便地增加新的功能,並且能夠方便地復用**,這種模式真實存在—裝飾模式。
其實裝飾模式的設計理念很簡單,就是利用聚合將要被新增功能的類聚合到用於新增功能的類的內部,正如裝飾模式的名字一樣,用乙個新的類將被裝飾的類包裝起來。
假設我們將需要被裝飾(新增功能)的類稱作component
而用於裝飾(新增功能)的類稱作decorator
。這樣,我們需要在decorator
內部聚合乙個component
,然後再將新的功能和舊的功能組合成為乙個呼叫鏈,現在**大致如下:
class component ;
virtual ~component ();
virtual
void operate(){};
};class decorator ;
virtual ~decorator ();
virtual
void operate()
};
現在我們已經為component
類新增了新的功能,可是這樣做問題很明顯,新增了新功能之後的decorator
根本無法用在那些原本使用component
的地方。ok那麼我們就讓decorator
成為乙個component
類,這樣就可以解決這個問題了。現在**修改如下:
class component ;
virtual ~component ();
virtual
void operate(){};
};class decorator : public component;
virtual ~decorator ();
virtual
void operate() override
};int main()
可是問題又出現了,我們如何靈活地改變需要新增的新功能呢?也就是addoperate
?我們可以將addoperate
寫成乙個虛函式,將這個職責推遲到子類當中去。修改後的**如下(**1):
class component ;
virtual ~component (){};
virtual
void operate();
};class decorator : public component;
public:
decorator (component* c):component(c){};
virtual ~decorator (){};
virtual
void operate() override
};class decoratorb : public decorator;
public:
decoratorb (component* c):decorator(c){};
virtual ~decoratorb (){};
};class decoratora : public decorator;
public:
decoratora (component* c):decorator(c){};
virtual ~decoratora (){};
};int main()
執行結果:
decoratora::addoperate
decoratorb::addoperate
decoratora::addoperate
decoratorb::addoperate
decoratora::addoperate
component::operate
這時總歸不方便,因為父類decorator
中規定了介面addoperate
,子類不想使用這個介面作為新增的新功能都不行,假設子類要新增乙個addstate
和addcounter
之類的功能呢?子類必須實現addstate
和addcounter
然後利用addoperate
呼叫這兩個方法,這樣的做法有點繞,乾脆將addoperate
的宣告也一併推遲到子類中讓子類來決定這個介面該是什麼,但是推遲了addoperate
的宣告,必然也會推遲對其的呼叫,這個呼叫依舊放在virtual void operate
中。修改後的**如下(**2):
class component ;
virtual ~component (){};
virtual
void operate()
};class decorator : public component
virtual ~decorator ()
virtual
void operate() override
};class decoratora : public decorator
public:
decoratora(component *d):decorator(d){}
virtual
void operate () override
};class decoratorb : public decorator
public:
decoratorb(component *d):decorator(d){}
virtual
void operate () override
};
以上的**就是裝飾模式的示例**。**2就是「正統」的裝飾模式實現,但我個人更喜歡**1中的實現,因為在增加新的功能的時候,不需要修改operate
方法,這個向外提供的方法,早早地固定好了,子類越少改動它,出錯的機率就越小。
下面給出裝飾模式的類圖和widget的整體方案
裝飾模式的優待點:
裝飾模式的缺點:
裝飾模式的適用場景:
c 設計模式之裝飾模式
裝飾模式能夠實現動態的為物件新增功能,是從乙個物件外部來給物件新增功能。通常給物件新增功能,要麼直接修改物件新增相應的功能,要麼派生對應的子類來擴充套件,抑或是使用物件組合的方式。顯然,直接修改對應的類這種方式並不可取。在物件導向的設計中,而我們也應該盡量使用物件組合,而不是物件繼承來擴充套件和復用...
c 設計模式之裝飾模式
裝飾器模式 動態地給乙個物件新增一些額外的工作職責,就增加功能來說,裝飾器模式比繼承的子類更靈活。裝飾模式的類結構圖 兌現 include include using namespace std class car class runcar public car public void showca...
C 設計模式之裝飾模式
在實際的應用過程中,裝飾模式還是被經常用到的。裝飾模式的本質是符合設計的原則 開閉原則 對修改封閉對新增開放 也就是說對於之前設計好的乙個類,如果想在這個類上新增一些新的功能或者在這個類的業務上新增一下新的業務,就可以在這個類的外層包裝乙個新類,新類就可以擴充套件你想要擴充套件的內容,這就是我理解的...