• [C++设计模式] decorator 装饰者模式


    《head first》中 的样例:咖啡店有各种咖啡饮料,能够往咖啡里面加各种调料变成还有一种饮料。假设使用继承的方式来为每一种饮料设计一个类,代码的复杂度非常easy膨胀,并且会继承父类的全部特性,因为继承为类型引入的静态特质,使得这样的扩展方式缺乏灵活性;同一时候,又掉入了还有一个陷阱,随着扩展功能的增多,子类也会增多,各种子类的组合,就会导致类的膨胀,最后,就会被淹没在类的海洋。

    这时大神们就发明了装饰者模式。在不改动如今有接口和实现类的基础上实现功能或者状态的加入。

    decorator(装饰者模式):动态地给一个对象加入一些额外的职责。就添加功能来说,Decorator模式相比生成子类更为灵活。

    装饰模式能够实现动态的为对象加入功能,是从一个对象外部来给对象加入功能。通常给对象加入功能,要么直接改动对象加入相应的功能。要么派生相应的子类来扩展。抑或是使用对象组合的方式。

    显然。直接改动相应的类这样的方式并不可取。在面向对象的设计中,而我们也应该尽量使用对象组合,而不是对象继承来扩展和复用功能。装饰器模式就是基于对象组合的方式。能够非常灵活的给对象加入所须要的功能。装饰器模式的本质就是动态组合。动态是手段,组合才是目的。

    总之,装饰模式是通过把复杂的功能简单化。分散化。然后再执行期间,依据须要来动态组合的这样一个模式。

    它使得我们能够给某个对象而不是整个类加入一些功能。



    Component:定义一个对象接口,能够给这些对象动态地加入职责;


    ConcreteComponent:定义一个详细的Component。继承自Component,重写了Component类的虚函数。


    Decorator:维持一个指向Component对象的指针,该指针指向须要被装饰的对象;并定义一个与Component接口一致的接口。


    ConcreteDecorator:向组件加入职责。


    使用场景:

    1,在不影响其它对象的情况下,以动态的。透明的方式给单个对象加入职责;

    2,处理那些能够撤销的职责;

    3,当不能採用生成子类的方法进行扩充时。一种情况是。可能存在大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。

    还有一种情况可能是由于类定义被隐藏。或类定义不能用于生成子类。

    演示样例代码:

    #include <iostream>
    using namespace std;
    class Component
    {
    public:
         virtual void Operation() = 0;
    };
    class ConcreteComponent : public Component
    {
    public:
         void Operation()
         {
              cout<<"I am no decoratored ConcreteComponent"<<endl;
         }
    };
    class Decorator : public Component
    {
    public:
         Decorator(Component *pComponent) : m_pComponentObj(pComponent) {}
         void Operation()
         {
              if (m_pComponentObj != NULL)
              {
                   m_pComponentObj->Operation();
              }
         }
    protected:
         Component *m_pComponentObj;
    };
    class ConcreteDecoratorA : public Decorator
    {
    public:
         ConcreteDecoratorA(Component *pDecorator) : Decorator(pDecorator){}
         void Operation()
         {
              AddedBehavior();
              Decorator::Operation();
         }
         void  AddedBehavior()
         {
              cout<<"This is added behavior A."<<endl;
         }
    };
    class ConcreteDecoratorB : public Decorator
    {
    public:
         ConcreteDecoratorB(Component *pDecorator) : Decorator(pDecorator){}
         void Operation()
         {
              AddedBehavior();
              Decorator::Operation();
         }
         void  AddedBehavior()
         {
              cout<<"This is added behavior B."<<endl;
         }
    };
    int main()
    {
         Component *pComponentObj = new ConcreteComponent();
         Decorator *pDecoratorAOjb = new ConcreteDecoratorA(pComponentObj);
         pDecoratorAOjb->Operation();
         cout<<"============================================="<<endl;
         Decorator *pDecoratorBOjb = new ConcreteDecoratorB(pComponentObj);
         pDecoratorBOjb->Operation();
         cout<<"============================================="<<endl;
         Decorator *pDecoratorBAOjb = new ConcreteDecoratorB(pDecoratorAOjb);
         pDecoratorBAOjb->Operation();
         cout<<"============================================="<<endl;
         delete pDecoratorBAOjb;
         pDecoratorBAOjb = NULL;
         delete pDecoratorBOjb;
         pDecoratorBOjb = NULL;
         delete pDecoratorAOjb;
         pDecoratorAOjb = NULL;
         delete pComponentObj;
         pComponentObj = NULL;
    }
    实现要点:

    1。接口的一致性;装饰对象的接口必须与它所装饰的Component的接口是一致的。因此,全部的ConcreteDecorator类必须有一个公共的父类。这样对于用户来说,就是统一的接口。


    2,省略抽象的Decorator类;当仅须要加入一个职责时,没有必要定义抽象Decorator类。由于我们经常要处理,现存的类层次结构而不是设计一个新系统。这时能够把Decorator向Component转发请求的职责合并到ConcreteDecorator中;


    3,保持Component类的简单性;为了保证接口的一致性,组件和装饰必需要有一个公共的Component类,所以保持这个Component类的简单性是很重要的,所以,这个Component类应该集中于定义接口而不是存储数据。

    对数据表示的定义应延迟到子类中,否则Component类会变得过于复杂和臃肿。因而难以大量使用。赋予Component类太多的功能。也使得详细的子类有一些它们它们不需要的功能大大增大。


    4。Component类在Decorator模式中充当抽象接口的角色,不应该去实现详细的行为。

    并且Decorator类对于Component类应该透明,换言之Component类无需知道Decorator类,Decorator类是从外部来扩展Component类的功能。

    5,Decorator类在接口上表现为“is-a”Component的继承关系,即Decorator类继承了Component类所具有的接口。但在实现上又表现为“has-a”Component的组合关系。即Decorator类又使用了另外一个Component类。我们能够使用一个或者多个Decorator对象来“装饰”一个Component对象,且装饰后的对象仍然是一个Component对象。,

    6,Decortor模式并不是解决“多子类衍生的多继承”问题,Decorator模式的应用要点在于解决“主体类在多个方向上的扩展功能”——是为“装饰”的含义;


    7,对于Decorator模式在实际中的运用能够非常灵活。假设仅仅有一个ConcreteComponent类而没有抽象的Component类。那么Decorator类能够是ConcreteComponent的一个子类。假设仅仅有一个ConcreteDecorator类,那么就没有必要建立一个单独的Decorator类,而能够把Decorator和ConcreteDecorator的责任合并成一个类。

    8,Decorator模式的长处是提供了比继承更加灵活的扩展,通过使用不同的详细装饰类以及这些装饰类的排列组合,能够创造出非常多不同行为的组合。


    9,因为使用装饰模式。能够比使用继承关系须要较少数目的类。使用较少的类,当然使设计比較易于进行。可是,在还有一方面。使用装饰模式会产生比使用继承关系很多其它的对象。很多其它的对象会使得查错变得困难,特别是这些对象看上去都非常相像。

  • 相关阅读:
    现身说法“好奇心害死人啊”
    代码错误集合(全是低级错误,欢迎高手前来指教)
    Return from TAOKEE
    泡了DOUBAN一个下午,思考中。。。
    买了两本书
    PDFBox,PDF文件处理
    数据库营销,DM杂志
    一个JS写的时间选择显示的控件,源文件下载
    WEB2.0新想法,让明星还有你无所遁行,让你我都做“狗仔队”
    hdu 1237 简单计算器 (栈的简单应用)
  • 原文地址:https://www.cnblogs.com/wzzkaifa/p/7121613.html
Copyright © 2020-2023  润新知