C++设计模式之装饰模式
前言
在實(shí)際開發(fā)時,你有沒有碰到過這種問題;開發(fā)一個類,封裝了一個對象的核心操作,而這些操作就是客戶使用該類時都會去調(diào)用的操作;而有一些非核心的操作,可能會使用,也可能不會使用;現(xiàn)在該怎么辦呢?
什么是裝飾模式?
在GOF的《設(shè)計(jì)模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》一書中對裝飾模式是這樣說的:動態(tài)地給一個對象添加一些額外的職責(zé)。就增加功能來說,Decorator模式相比生成子類更為靈活。
裝飾模式能夠?qū)崿F(xiàn)動態(tài)的為對象添加功能,是從一個對象外部來給對象添加功能。通常給對象添加功能,要么直接修改對象添加相應(yīng)的功能,要么派生對應(yīng)的子類來擴(kuò)展,抑或是使用對象組合的方式。顯然,直接修改對應(yīng)的類這種方式并不可取。在面向?qū)ο蟮脑O(shè)計(jì)中,而我們也應(yīng)該盡量使用對象組合,而不是對象繼承來擴(kuò)展和復(fù)用功能。裝飾器模式就是基于對象組合的方式,可以很靈活的給對象添加所需要的功能。裝飾器模式的本質(zhì)就是動態(tài)組合。動態(tài)是手段,組合才是目的。總之,裝飾模式是通過把復(fù)雜的功能簡單化,分散化,然后再運(yùn)行期間,根據(jù)需要來動態(tài)組合的這樣一個模式。它使得我們可以給某個對象而不是整個類添加一些功能。
UML類圖
Component:定義一個對象接口,可以給這些對象動態(tài)地添加職責(zé);
ConcreteComponent:定義一個具體的Component,繼承自Component,重寫了Component類的虛函數(shù);
Decorator:維持一個指向Component對象的指針,該指針指向需要被裝飾的對象;并定義一個與Component接口一致的接口;
ConcreteDecorator:向組件添加職責(zé)。
代碼實(shí)現(xiàn)
/* ** FileName : DecoratorPatternDemo ** Author : Jelly Young ** Date : 2013/12/19 ** Description : More information, please go to http://www.jellythink.com */ #include <iostream> using namespace std; class Component { public:virtual void Operation() = 0; }; class ConcreteComponent : public Component { public:void Operation(){cout<<"I am no decoratored ConcreteComponent"<<endl;} }; class Decorator : public Component { public:Decorator(Component *pComponent) : m_pComponentObj(pComponent) {}void Operation(){if (m_pComponentObj != NULL){m_pComponentObj->Operation();}} protected:Component *m_pComponentObj; }; class ConcreteDecoratorA : public Decorator { public:ConcreteDecoratorA(Component *pDecorator) : Decorator(pDecorator){}void Operation(){AddedBehavior();Decorator::Operation();}void AddedBehavior(){cout<<"This is added behavior A."<<endl;} }; class ConcreteDecoratorB : public Decorator { public:ConcreteDecoratorB(Component *pDecorator) : Decorator(pDecorator){}void Operation(){AddedBehavior();Decorator::Operation();}void AddedBehavior(){cout<<"This is added behavior B."<<endl;} }; int main() {Component *pComponentObj = new ConcreteComponent();Decorator *pDecoratorAOjb = new ConcreteDecoratorA(pComponentObj);pDecoratorAOjb->Operation();cout<<"============================================="<<endl;Decorator *pDecoratorBOjb = new ConcreteDecoratorB(pComponentObj);pDecoratorBOjb->Operation();cout<<"============================================="<<endl;Decorator *pDecoratorBAOjb = new ConcreteDecoratorB(pDecoratorAOjb);pDecoratorBAOjb->Operation();cout<<"============================================="<<endl;delete pDecoratorBAOjb;pDecoratorBAOjb = NULL;delete pDecoratorBOjb;pDecoratorBOjb = NULL;delete pDecoratorAOjb;pDecoratorAOjb = NULL;delete pComponentObj;pComponentObj = NULL; }使用場合
注意事項(xiàng)
實(shí)現(xiàn)要點(diǎn)
與橋接模式的區(qū)別
之前總結(jié)了C++設(shè)計(jì)模式——橋接模式;你會發(fā)現(xiàn),二者都是為了防止過度的繼承,從而造成子類泛濫的情況。那么二者之間的主要區(qū)別是什么呢?橋接模式的定義是將抽象化與實(shí)現(xiàn)化分離(用組合的方式而不是繼承的方式),使得兩者可以獨(dú)立變化。可以減少派生類的增長。如果光從這一點(diǎn)來看的話,和裝飾者差不多,但兩者還是有一些比較重要的區(qū)別:
總結(jié)
裝飾模式重點(diǎn)在裝飾,對核心功能的裝飾作用;將繼承中對子類的擴(kuò)展轉(zhuǎn)化為功能類的組合,從而將需要對子類的擴(kuò)展轉(zhuǎn)嫁給用戶去進(jìn)行調(diào)用組合,用戶如何組合由用戶去決定。我在學(xué)習(xí)裝飾模式時,就是重點(diǎn)分析了“裝飾”這個詞,我們都知道,裝飾是在一個核心功能上添加一些附屬功能,從而讓核心功能發(fā)揮更大的作用,但是最終它的核心功能是不能丟失的。這就好比我們進(jìn)行windows shell開發(fā)時,我們是對windows的這層殼進(jìn)行了功能的裝飾,從而實(shí)現(xiàn)了我們需要的一些裝飾功能,但是最終的功能還是由windows shell去完成。這就好比,我們的裝飾就是給核心功能添加了一層外衣,讓它看起來更漂亮和完美。
Decorator模式除了采用組合的方式取得了比采用繼承方式更好的效果,Decorator模式還給設(shè)計(jì)帶來一種“即用即付”的方式來添加職責(zé)。在OO設(shè)計(jì)和分析經(jīng)常有這樣一種情況:為了多態(tài),通過父類指針指向其具體子類,但是這就帶來另外一個問題,當(dāng)具體子類要添加新的職責(zé),就必須向其父類添加一個這個職責(zé)的抽象接口,否則是通過父類指針是調(diào)用不到這個方法了。這樣處于高層的父類就承載了太多的特征(方法),并且繼承自這個父類的所有子類都不可避免繼承了父類的這些接口,但是可能這并不是這個具體子類所需要的。而在Decorator模式提供了一種較好的解決方法,當(dāng)需要添加一個操作的時候就可以通過Decorator模式來解決,你可以一步步添加新的職責(zé)。
雷哥就要走了,且行且珍重!
2013年12月21日 于大連,東軟。
===修改日志===
2015年2月4日 修改了個別錯別字,重新進(jìn)行了code review。
總結(jié)
以上是生活随笔為你收集整理的C++设计模式之装饰模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++设计模式之适配器模式
- 下一篇: C++设计模式之桥接模式