zoukankan      html  css  js  c++  java
  • Decorator(装饰)模式

    1. 概述

           若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一个基本特性。如果已经存在的一个类缺少某些方法,或者须要给方法添加更多的功能(魅力),你也许会仅仅继承这个类来产生一个新类—这建立在额外的代码上。

          通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法。但是这种方法是静态的,用户不能控制增加行为的方式和时机。如果  你希望改变一个已经初始化的对象的行为,你怎么办?或者,你希望继承许多类的行为,改怎么办?前一个,只能在于运行时完成,后者显然时可能的,但是可能会导致产生大量的不同的类—可怕的事情。

    2. 问题

    你如何组织你的代码使其可以容易的添加基本的或者一些很少用到的 特性,而不是直接不额外的代码写在你的类的内部?

    3. 解决方案

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

           装饰器模式提供了改变子类的灵活方案。装饰器模式在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

           当用于一组子类时,装饰器模式更加有用。如果你拥有一族子类(从一个父类派生而来),你需要在与子类独立使用情况下添加额外的特性,你可以使用装饰器模式,以避免代码重复和具体子类数量的增加。

    4. 适用性

    以下情况使用Decorator模式

    1)• 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

    2)• 处理那些可以撤消的职责。

    3)• 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,

    为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。

    另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

    5. 结构

    UML图如下



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

    ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责。
    Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator的存在的。
    至于ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能。

    要善于变通,如果只有一个ConcreteComponent类而没有抽象的Component类,那么Decorator类可以是ConcreteComponent的一个子类。
    同样道理,如果只有一个ConcreteDecorator类,那么就没有必要建立一个单独的Decorator类,而可以把Decorator和ConcreteDecorator的责任合并成一个类。

    新加入的东西仅仅是为了满足一些只在某种特定情况下才会执行的特殊行为 的需要。而装饰模式却提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因此,当需要执行特殊行为 时,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象了。

    代码如下

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

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

    总结

    一般,当系统需要新功能的时候,是向旧的类中添加新的代码。这些新加的代码通常装饰了原有类的核心职责或主要行为,但这种做法的问题在于,它们在主类中加入了新的字段,新的方法和新的逻辑,从而增加了主类的复杂度,并且新加入的东西仅仅是为了满足一些只在某种特定情况下才会执行的特殊行为的需要。而装饰模式却提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象了。

    那么装饰模式的优点有:1 把类中的装饰功能从类中搬移去除,这样可以简化原有的类,这样做更大的好处就是有效地把类的核心职责和装饰功能区分开了。而且可以去除相关类中重复的装饰逻辑。

  • 相关阅读:
    资料下载
    sublime安装AngularJS插件
    Zen Coding: 一种快速编写HTML/CSS代码的方法[Emmet]
    手机号码归属地API
    浅谈JavaScript中的作用域
    原生ajax、jsoup
    Java排序:选择排序
    Java排序:冒泡排序
    Oracle系列一、基本术语
    linux jdk tomcat 安装
  • 原文地址:https://www.cnblogs.com/wuchanming/p/4486038.html
Copyright © 2011-2022 走看看