天天看點

【設計模式學習筆記十】【結構型模式】【裝飾模式(Decorator)】

本文是學習劉偉技術部落格和《設計模式-可複用面向對象軟體的基礎》筆記,部落格連結:http://blog.csdn.net/lovelion/article/details/17517213

主要是對部落格和書本做提煉和記錄,更多是對設計模式的基礎架構學習,細節将略去,側重對每個設計模式架構的了解。

我應該了解和掌握的:

1)能夠畫出這個設計模式的架構框圖;

2)能夠根據架構框圖寫出對應的僞代碼;

3)這個模式的應用場景,主要優缺點。

1.裝飾模式

裝飾模式在不改變對象本身功能的基礎上添加額外的功能,比如給照片添加一個相框。同時他也是一種替代繼承的技術,使用關聯取代繼承;在裝飾模式中引入裝飾類,在裝飾類中既可以調用待裝飾的原有類方法,還可以新增方法,以擴充原有功能。

(1)定義

裝飾模式:動态的給一個對象添加一些額外的職責。就新增功能來說,Decorator模式相比生成子類更為靈活。

1) 裝飾模式結構圖

【設計模式學習筆記十】【結構型模式】【裝飾模式(Decorator)】

2)參與者

a) Component(抽象構件):定義一個對象業務方法,是具體建構和抽象裝飾類的共同父類,用戶端針對它程式設計。

b) ConcreteComponent(具體構件):定義具體構件,實作父類業務方法,裝飾類将會給這個對象增加額外的職責。

c) Decorator(抽象裝飾類):抽象構件子類,用于關聯一個抽象構件的指針,并定義一個與Component一緻的接口,直接調用裝飾之前對象的業務方法。

d) ConcreteDecorator(具體裝飾類):向具體構件增加額外的職責,不同的具體裝飾類增加不同的職責。調用抽象裝飾類的operation方法,同時增加新的業務方法,這邊是裝飾額外的功能。

3) 看圖寫代碼

/*
 ** FileName     : DecoratorPattern
 ** Author       : lin005
 ** Date         : 2015/01/27
 ** Description  : More information, please go to http://blog.csdn.net/amd123456789
 */
class Component
{
public:
    virtual void operation() = 0;
};
//具體建構類
class ConcreteComponent:public Component
{
public:
    void operation()
    {
        cout<<"ConcreteComponent"<<endl;
    }
};
//抽象裝飾類
class Decorator:public Component
{
public:
    //注入抽象類,保持一個對component的引用
    Decorator(Component* c)
    {
        _component = c;
    }
    virtual void operation()//直接調用component的方法
    {
        _component->operation();
    }
    ~Decorator()
    {
        if(_component != NULL)
        {
            delete _component;
            _component = NULL;
        }
    }
protected:
    //關聯一個component
    Component* _component;
};
//具體狀态裝飾類
class ComcreteDecoratorA:public Decorator
{
public:
    //注入一個component對象
    ComcreteDecoratorA(Component* c):Decorator(c){}
    //對客戶透明,始終還是調用operation()
    virtual void operation()
    {
        //增加state狀态
        addstate();
        Decorator::operation();
    }
    //裝飾類要添加的職能
    void addstate()
    {
        cout<<"要裝飾的狀态方法"<<endl;
    }
};
//具體行為裝飾類
class ComcreteDecoratorB:public Decorator
{
public:
    //注入一個component對象
    ComcreteDecoratorB(Component* c):Decorator(c){}
    virtual void operation()
    {
        //裝飾行為職能
        addbehavior();
        Decorator::operation();
    }
    void addbehavior()
    {
        cout<<"要裝飾的行為方法"<<endl;
    }
};
//用戶端測試
int main(int argc, const char * argv[]) {
    //用戶端針對抽象程式設計
    Component *c;
    Component* dA;
    Component* dB;
    Component* dAB;
    
    c = new ConcreteComponent();//具體構件對象,即要裝飾前的對象
    dA = new ComcreteDecoratorA(c);//具體裝飾對象A
    dB = new ComcreteDecoratorB(c);//具體裝飾對象B
    dAB = new ComcreteDecoratorA(dB);//同時裝飾A和B,非常友善,直接嵌套

    c->operation();
    dA->operation();
    dB->operation();
    dAB->operation();
    
    return 0;
}
           

(2)總結

1)優點:

a) 對于擴充一個對象的功能,裝飾模式比靜态繼承更靈活,也很容易重複添加一個特性,不會導緻類的個數急劇增加。

b) 可以對一個對象進行多次裝飾,通過使用不同的具體裝飾類以及這些裝飾類的排列組合,得到功能更為強大的對象。

c) 符合開閉,具體構件類和具體裝飾類可以獨立變化,按需增加新的具體構件類和具體裝飾類。

2)缺點

a) 會産生許多小對象;這些對象僅僅在他們互相連接配接的方式上有所不同,而不是他們的類或是他們的屬性值有所不同。

b) 對于了解這些系統的人來說,很容易對他們進行定制,但是很難學習這些系統,排錯也困難。

3) 注意事項

a) 接口一緻性。裝飾對象的接口必須與他所裝飾的component的接口是一緻的。

b) 保持Component類的簡單性。它應集中于定義接口而不是存儲資料,對于資料的表示應延遲到子類,否則Component會變得過于複雜的龐大,難以大量使用。我們應該通過裝飾類對其進行擴充。

c) 可以省略抽象的Decorator類,當你僅需要添加一個職責時,沒必要定義抽象Decotator類。你常常需要處理現存的類層次結構而不是設計一個新的系統,這時可以把Decorator向Component轉發請求的職責合并到ComcreteDecorator中。

d) 如果隻有一個具體構件類,那麼抽象裝飾類可以作為該具體構件結構類的直接子類。如下圖:

【設計模式學習筆記十】【結構型模式】【裝飾模式(Decorator)】

(3)适用場景

1)在不影響其他對象的情況下,以動态、透明的方式給單個對象添加職責。

2)處理那些可以撤銷的職責,按需再進行添加。同時裝飾者模式的行為具有可疊加性。

3)當不能采用生成子類的方法進行擴充。一種是,可能有大量獨立的擴充,為支援每一種組合将産生大量的子類,使得子類數目呈爆炸性增長。另一種是可能因為類定義被隐藏,或類定義不能生成子類。

繼續閱讀