程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 設計模式C++描述----10.裝飾(Decorator)模式

設計模式C++描述----10.裝飾(Decorator)模式

編輯:C++入門知識

一. 舉例

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

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

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

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

第二種方案:

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

\

代碼如下:


[cpp] //定義一個對象接口,可以給這些對象動態地添加職責  
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; 

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

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

//定義一個具體的對象 www.2cto.com
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. 有效地把類的核心職責和裝飾功能區分開,而且可以去除相關類中重復的裝飾邏輯。


三. 問題討論

從上圖可以看到 Decorator 是繼承於 Component 的,也就和 ConcreteComponent 成了兄弟了,但是 Decorator 的作用卻是修飾 ConcreteComponent 的,這點好像是很怪怪的!!最說不通的是Decorator 與 Component 是沒有is-a關系的!!


我個人覺得:

1. 這個繼承關系,不應該是我們要重點關注的。這裡使用繼承主要是為了要重用 Operation() 這個接口,以達修飾的目的。

2. 重點是 Decorator 與 Component 這個組合關系。裝飾類裡有一個Component 指針,正是由於它的存在才能修飾到具體的 Component 對象。

 


作者 lwbeyond

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved