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;
}



 

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