zoukankan      html  css  js  c++  java
  • 【设计模式】装饰模式

    1、定义

    1.1 标准定义

      装饰模式(Decorator Pattern)是一种比较常见的模式,其定义如下:

      Attach additional responsibilities to an object dynamically keeping the same interface.Decorators provide a flexiblealternative to subclassing for extending functionality.(动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。)

    1.2 通用类图

      ● Component抽象构件
      Component是一个接口或者是抽象类, 是定义我们最核心的对象, 就是最原始的对象。
      注意:在装饰模式中,必然有一个最基本、最核心、最原始的接口或抽象类充当Component抽象构件。

      ● ConcreteComponent 具体构件
      ConcreteComponent是最核心、最原始、最基本的接口或抽象类的实现,你要装饰的就是它。

      ● Decorator装饰角色
      一般是一个抽象类,做什么用呢?实现接口或者抽象方法,它里面可不一定有抽象的方法呀,在它的属性里必然有一个private变量指向Component抽象构件。

      ● 具体装饰角色
      ConcreteDecoratorA和ConcreteDecoratorB是两个具体的装饰类, 你要把你最核心的、最原始的、最基本的东西装饰成其他东西。

    2、实现

    2.1 类图

      Component是定义一个对象接口,可以给这些对象动态地添加职责。

      ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责。

      Decorator为装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator的存在的。至于ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能。

      要善于变通,如果只有一个ConcreteComponent类而没有抽象的Component类,那么Decorator类可以是ConcreteComponent的一个子类。

      同样道理,如果只有一个ConcreteDecorator类,那么就没有必要建立一个单独的Decorator类,而可以把Decorator和ConcreteDecorator的责任合并成一个类。

    2.2 代码

    2.2.1 装饰类

    //Decorator.h
    
    #ifndef _DECORATOR_H_
    #define _DECORATOR_H_
    
    //Component抽象类,定义该类对象的接口
    class Component
    {
    public:
        virtual ~Component();
        virtual void Operation()=0;
    protected:
        Component();
    };
    
    //ConcreteDecorator:具体的Component对象,可以给该对象动态 添加职责
    class ConcreteComponent:public Component
    {
    public:
        ConcreteComponent();
        ~ConcreteComponent();
        virtual void Operation();
    };
    
    //Decorator:装饰抽象类,继承自Component
    class Decorator:public Component
    {
    public:
        Decorator(Component* com);
        void SetComponent(Component* com);
        virtual ~Decorator();
        virtual void Operation();
    protected:
        Component* _com;
    };
    
    //ConcreteDecorator就是具体的装饰对象之一,起到给Component添加职责的功能
    class ConcreteDecoratorA:public Decorator
    {
    public:
        ConcreteDecoratorA(Component* com);
        ~ConcreteDecoratorA();
        virtual void Operation();
        void AddBehavorA();
    };
    
    //ConcreteDecorator就是具体的装饰对象之二,起到给Component添加职责的功能
    class ConcreteDecoratorB:public Decorator
    {
    public:
        ConcreteDecoratorB(Component* com);
        ~ConcreteDecoratorB();
        virtual void Operation();
        void AddBehavorB();
    };
    
    //ConcreteDecorator就是具体的装饰对象之三,起到给Component添加职责的功能
    class ConcreteDecoratorC:public Decorator
    {
    public:
        ConcreteDecoratorC(Component* com);
        ~ConcreteDecoratorC();
        virtual void Operation();
        void AddBehavorC();
    };
    
    //ConcreteDecorator就是具体的装饰对象之四,起到给Component添加职责的功能
    class ConcreteDecoratorD:public Decorator
    {
    public:
        ConcreteDecoratorD(Component* com);
        ~ConcreteDecoratorD();
        virtual void Operation();
        void AddBehavorD();
    };
    
    //只添加一种装饰,则不用抽象出装饰基类
    class DecoratorOnlyOne:public Component
    {
    public:
        DecoratorOnlyOne(Component* com);
        ~DecoratorOnlyOne();
        virtual void Operation();
        void AddBehavor();
    private:
        Component* _com;
    };
    
    //如果只有一个ConcreteComponent类而没有抽象的Component类,那么Decorator类可以是ConcreteComponent的一个子类。
    //
    #endif
    // Decorator.cpp
    
    #include "Decorator.h"
    #include <iostream>
    
    using namespace std;
    
    Component::Component(){}
    
    Component::~Component()
    {
        cout << "~Component" << endl;
    }
    
    ConcreteComponent::ConcreteComponent(){}
    
    ConcreteComponent::~ConcreteComponent()
    {
        cout << "~ConcreteComponent" << endl;
    }
    
    void ConcreteComponent::Operation()
    {
        cout << "原职责:ConcreteComponent::Operation" << endl;
    }
    
    Decorator::Decorator(Component* com)
    {
        this->_com = com;
    }
    
    void Decorator::SetComponent(Component* com)
    {
        this->_com = com;
    }
    
    Decorator::~Decorator()
    {
        cout << "~Decorator" << endl;
        delete this->_com;
        this->_com = NULL;
    }
    
    void Decorator::Operation(){}
    
    ConcreteDecoratorA::ConcreteDecoratorA(Component* com):Decorator(com){}
    
    ConcreteDecoratorA::~ConcreteDecoratorA()
    {
        cout << "~ConcreteDecoratorA" << endl;
    }
    
    void ConcreteDecoratorA::Operation()
    {
        this->_com->Operation();
        //附加职责A
        this->AddBehavorA();
    }
    
    void ConcreteDecoratorA::AddBehavorA()
    {
        cout << "附加职责A:ConcreteDecoratorA::AddBehavorA" << endl;
    }
    
    ConcreteDecoratorB::ConcreteDecoratorB(Component* com):Decorator(com){}
    
    ConcreteDecoratorB::~ConcreteDecoratorB()
    {
        cout << "~ConcreteDecoratorB" << endl;
    }
    
    void ConcreteDecoratorB::Operation()
    {
        this->_com->Operation();
        //附加职责B
        this->AddBehavorB();
    }
    
    void ConcreteDecoratorB::AddBehavorB()
    {
        cout << "附加职责B:ConcreteDecoratorB::AddBehavorB" << endl;
    }
    
    ConcreteDecoratorC::ConcreteDecoratorC(Component* com):Decorator(com){}
    
    ConcreteDecoratorC::~ConcreteDecoratorC()
    {
        cout << "~ConcreteDecoratorC" << endl;
    }
    
    void ConcreteDecoratorC::Operation()
    {
        this->_com->Operation();
        //附加职责C
        this->AddBehavorC();
    }
    
    void ConcreteDecoratorC::AddBehavorC()
    {
        cout << "附加职责C:ConcreteDecoratorC::AddBehavorC" << endl;
    }
    
    ConcreteDecoratorD::ConcreteDecoratorD(Component* com):Decorator(com){}
    
    ConcreteDecoratorD::~ConcreteDecoratorD()
    {
        cout << "~ConcreteDecoratorD" << endl;
    }
    
    void ConcreteDecoratorD::Operation()
    {
        this->_com->Operation();
        //附加职责D
        this->AddBehavorD();
    }
    
    void ConcreteDecoratorD::AddBehavorD()
    {
        cout << "附加职责D:ConcreteDecoratorD::AddBehavorD" << endl;
    }
    
    //**************只添加一种修饰******************
    DecoratorOnlyOne::DecoratorOnlyOne(Component* com):_com(com)
    {
    }
    
    DecoratorOnlyOne::~DecoratorOnlyOne()
    {
        cout << "~DecoratorOnlyOne" << endl;
        delete this->_com;
        this->_com = NULL;
    }
    
    void DecoratorOnlyOne::Operation()
    {
        this->_com->Operation();
        this->AddBehavor();
    }
    
    void DecoratorOnlyOne::AddBehavor()
    {
        cout << "附加唯一职责:DecoratorOnlyOne::AddBehavor" << endl;
    }

    2.2.3 调用

    // main.cpp
    
    #include "Decorator.h"
    #include <iostream>
    
    using namespace std;
    int main()
    {
        Component* pCom = new ConcreteComponent();        //要装饰的对象
        Decorator* pDec = NULL;
        pDec = new ConcreteDecoratorA(pCom);            //给装饰对象附加职责A
        pDec = new ConcreteDecoratorB(pDec);            //给装饰对象附加职责B
        pDec = new ConcreteDecoratorC(pDec);            //给装饰对象附加职责C
        pDec = new ConcreteDecoratorD(pDec);            //给装饰对象附加职责D
        pDec->Operation();
    
        cout << "-------------------------------" << endl;
    
        //只添加一种修饰
        Component* pCom1 = new ConcreteComponent();
        DecoratorOnlyOne* pDec1 = new DecoratorOnlyOne(pCom1);
        pDec1->Operation();
    
        cout << "-------------------------------" << endl;
    
        delete pDec;
        cout << "-------------------------------" << endl;
    
        delete pDec1;
    
        return 0;
    }

    2.2.4 运行结果

    3、优缺点

    3.1 优点

      ● 装饰类和被装饰类可以独立发展,而不会相互耦合。换句话说,Component类无须知道Decorator类,Decorator类是从外部来扩展Component类的功能,而Decorator也不用知道具体的构件。
      ● 装饰模式是继承关系的一个替代方案。我们看装饰类Decorator,不管装饰多少层,返回的对象还是Component,实现的还是is-a的关系。
      ● 装饰模式可以动态地扩展一个实现类的功能,这不需要多说,装饰模式的定义就是如此 。

    3.2 缺点

      对于装饰模式记住一点就足够了:多层的装饰是比较复杂的。为什么会复杂呢?你想想看,就像剥洋葱一样,你剥到了最后才发现是最里层的装饰出现了问题,想象一下工作量吧,因此,尽量减少装饰类的数量,以便降低系统的复杂度。

    4、应用场景

      ● 需要扩展一个类的功能, 或给一个类增加附加功能。
      ● 需要动态地给一个对象增加功能, 这些功能可以再动态地撤销。
      ● 需要为一批的兄弟类进行改装或加装功能, 当然是首选装饰模式。

  • 相关阅读:
    原生态Vim使用快捷键
    Django 搭建博客记(二)
    Django搭建博客记(一)
    草稿
    骨骼动画的实现(OpenGL实现)
    场景内容的再现
    实现Ogre的脚本分离
    Bullet物理引擎在OpenGL中的应用
    linux fork进程请谨慎多个进程/线程共享一个 socket连接,会出现多个进程响应串联的情况。
    多开发机别名跳转脚本片段
  • 原文地址:https://www.cnblogs.com/ChinaHook/p/7252908.html
Copyright © 2011-2022 走看看