Decorator模式

一. 舉例

我之前做過一個文件系統就叫 MyFileSys 吧,後來的話,客戶想加入一些附加功能,比如壓縮、加密、殺毒之類的操作,這些附加操作沒有先後順序,比如你可以先壓縮再加密,也可以先殺毒再壓縮,等等。

這些附加功能是可選的,有的客戶要這些功能,有的不要,有的要其中的幾種附加功能等等。怎麼設計呢?

第一種方案:
直接修改這個獨立的文件系統 MyFileSys,對於不同的客戶實現不同的文件系統。

 

 

後來隨着客戶的增多,發現維護和修改的工作量越來越大。因爲每增加一個客戶就要重新生成一個類,然後把客戶想要的附加功能加入,更加鬱悶的是,只針對一個客戶有時也是要修改很多次,客戶今天要這些附加功能,明天又想加入另外一些功能,這樣改來改去,維護工作量也是很大的。

第二種方案:

後來改用第二種方案,實現一個單獨的附加功能類,保持原文件系統不變,這樣在客戶端就可以輕鬆的加入一些附加功能。

 

 

//定義一個對象接口,可以給這些對象動態地添加職責
class FileSys
{
public:
    virtual ~FileSys()
    {
    }

    virtual void Operation()
    {
    }
protected:
    FileSys()
    {
    }
};

//定義一個具體的對象
class MyFileSys:public FileSys
{
public:
    MyFileSys()
    {
    }

    ~MyFileSys()
    {
    }

    void Operation()
    {
        cout<<"MyFileSys operation..."<<endl;
    }
};

//裝飾抽象類
class Decorator:public FileSys
{
public:
    Decorator(FileSys* fileSys)
    {
        this->_fileSys = fileSys;
    }

    virtual ~Decorator()
    {
        delete _fileSys;
    }

    void Operation()
    {
    }
protected:
    FileSys* _fileSys;
};

//壓縮裝飾類
class ZipDecorator:public Decorator
{
public:
    ZipDecorator(FileSys* fileSys):Decorator(fileSys)
    {
    }

    ~ZipDecorator()
    {
    }
    
    void Operation()
    {
        _fileSys->Operation(); //首先運行以前的功能
        
        this->AddedZipBehavior(); //附加功能
    }
    
    void AddedZipBehavior()
    {
        cout<<"Added Zip Behavior...."<<endl;
    }
};

//殺毒裝飾類
class KillVirDecorator:public Decorator
{
public:
    KillVirDecorator(FileSys* fileSys):Decorator(fileSys)
    {
    }
    
    ~KillVirDecorator()
    {
    }
    
    void Operation()
    {
        _fileSys->Operation();
        
        this->AddedKillVirBehavior();
    }
    
    void AddedKillVirBehavior()
    {
        cout<<"Added Kill Virus Behavior...."<<endl;
    }
};

//加密裝飾類
class EncryptDecorator:public Decorator
{
public:
    EncryptDecorator(FileSys* fileSys):Decorator(fileSys)
    {
    }
    
    ~EncryptDecorator()
    {
    }
    
    void Operation()
    {
        _fileSys->Operation();
        
        this->AddedEncrypeBehavior();
    }
    
    void AddedEncrypeBehavior()
    {
        cout<<"Added Encrypt Behavior...."<<endl;
    }
};

//////////////////////////////////////////////////////////////////////////
//測試
int main()
{
    FileSys* fileSys = new MyFileSys();
    
    Decorator* dec1 = new ZipDecorator(fileSys);  //在原文件系統上,加入壓縮功能
    Decorator* dec2 = new KillVirDecorator(dec1); //在之前的基礎上,加入殺毒功能
    Decorator* dec3 = new EncryptDecorator(dec2); //再加入加密功能

    dec3->Operation();

    return 0;
}


這樣之後,如果要添加附加功能,實現起來就很方便了。這種模式就是裝飾模式。

二. 裝飾模式

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

 

 

說明:

Componet,主要是定義一個接口,通過這個接口可以給這些對象(ConcreteComponent)添加職責。

Dectorator,裝飾類,通過外類(ConcreteDecorator)來擴展Component 類的功能,對於Component來說,是無需知道這個抽象類的存在的。

ConcreteDecorator,具體裝飾類,添加具體的附加功能。

優點:

1. 裝飾類是爲已有功能動態地添加更多功能的一種方式。

2. 有效地把類的核心職責裝飾功能區分開,而且可以去除相關類中重複的裝飾邏輯。

 

三. 問題討論

在結構圖中,ConcreteComponentDecorator需要有同樣的接口,因此ConcreteComponentDecorator有着一個共同的父類。這裏有人會問,讓Decorator直接維護一個指向ConcreteComponent引用(指針)不就可以達到同樣的效果,答案是肯定並且是否定的。肯定的是你可以通過這種方式實現,否定的是你不要用這種方式實現,因爲通過這種方式你就只能爲這個特定的ConcreteComponent提供修飾操作了,當有了一個新的ConcreteComponent你又要去新建一個Decorator來實現。但是通過結構圖中的ConcreteComponentDecorator有一個公共基類,就可以利用OO中多態的思想來實現只要是Component型別的對象都可以提供修飾操作的類,這種情況下你就算新建了100Component型別的類ConcreteComponent,也都可以由Decorator一個類搞定。這也正是Decorator模式的關鍵和威力所在了。

       當然如果你只用給Component型別類添加一種修飾,則Decorator這個基類就不是很必要了。

 

//test.h
/**///////////////////////////////////////////////////////////////////////////
class Component
{
public:
    Component(){}
    virtual ~Component(){}

    //純虛函數
    virtual void Operation() = 0;
};

//抽象基類,維護一個指向Component對象的指針
class Decorator : public Component
{
public:
    Decorator(Component* pComponent) : m_pComponent(pComponent){}
    virtual ~Decorator();
protected:
    Component* m_pComponent;
};

//派生自Component,需要給他動態添加職責
class ConCreateComponent : public Component
{
public:
    ConCreateComponent(){}
    virtual ~ConCreateComponent(){}

    virtual void Operation();
};

//派生自Decorator,爲ConCreateComponent動態添加職責
class ConCreateDecorator : public Decorator
{
public:
    ConCreateDecorator(Component* pComponent) : Decorator(pComponent){}
    virtual ~ConCreateDecorator(){}

    virtual void Operation();
private:
    void AddedBehavior(); //動態添加的職責
};


 

// test.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include "test.h"

//////////////////////////////////////////////////////////////////////////
Decorator::~Decorator()
{
    delete m_pComponent;
    m_pComponent = NULL;
}
void ConCreateComponent::Operation()
{
    std::cout << "Operation of ConCreateComponent\n";
}
void ConCreateDecorator::Operation()
{
    m_pComponent->Operation();
    AddedBehavior();
}
void ConCreateDecorator::AddedBehavior()
{
    std::cout << "AddedBehavior of ConCreateDecorator\n";
}
//////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[])
{
    Component* Pcomponent = new ConCreateComponent;
    //用這個對象去初始化一個Decorator對象
    //通過多態調用動態添加了職責
    Decorator* pDecorator = new ConCreateDecorator(Pcomponent);
    pDecorator->Operation();
    
    delete pDecorator;

    system("pause");
    return 0;
}



 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章