设计模式(八)——装饰模式

一、装饰模式简介

1、装饰模式简介

    装饰器模式可以动态地给一个对象添加一些额外的职责

    装饰模式的特点:

    A装饰对象和真实对象有相同的接口。客户端对象可以使用和真实对象相同的方式和装饰对象交互。

    B装饰对象包含一个真实对象的索引(reference
    C装饰对象接受所有的来自客户端的请求,并把请求转发给真实的对象。

    D装饰对象可以在转发来自客户端的请求以前或以后增加一些附加功能。可以确保在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。在面向对象的设计中,通常通过继承来实现对给定类的功能扩展。通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法。但继承是静态的,用户不能控制增加行为的方式和时机。如果希望改变一个已经初始化的对象的行为,只能在于运行时完成;如果希望继承许多类的行为,则可能会导致产生大量的不同的类。

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

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

2、装饰模式角色

 Component:对象抽象基类,定义一个对象接口,可以给对象动态地添加职责。

 ConcreteComponent被装饰者定义一个将要被装饰增加功能的类,可以给具体的对象添加一些职责。

        Decorator装饰抽象类,继承了Component维持一个指向构件Component对象的实例,并定义一个与抽象组件角色Component接口一致的接口从外类来扩展Component类的功能,但对于Component来说是无需知道Decorator的存在的。
        ConcreteDecorator具体的装饰对象,起到给Component添加职责的功能。

如果只有一个ConcreteComponent类而没有抽象的Component类,那么Decorator类可以是ConcreteComponent的一个子类。如果只有一个ConcreteDecorator类,那么就没有必要建立一个单独的Decorator类,而可以把DecoratorConcreteDecorator的责任合并成一个类。

3、装饰模式优缺点

    优点:

        A、比静态继承更灵活与对象的静态继承(多重继承)相比,装饰模式提供了更加灵活的向对象添加职责的方式。可以用添加和分离的方法,用装饰在运行时刻增加和删除职责。继承机制要求为每个添加的职责创建一个新的子类会产生许多新的类,并且会增加系统的复杂度。此外,为一个特定的Component类提供多个不同的 Decorator类,这就使得可以对一些职责进行混合和匹配。使用Decorator模式可以很容易地重复添加一个特性。

    B避免在层次结构高层的类有太多的特征。装饰模式提供了一种即用即付的方法来添加职责并不试图在一个复杂的可定制的类中支持所有可预见的特征相反,可以定义一个简单的类,并且用Decorator类给简单类逐渐地添加功能从简单的部件组合出复杂的功能。

    C把类的装饰功能从类中搬移去除,可以简化原有的类。

    D有效地把类的核心职责和装饰功能区分开来,而且可以去除相关类中重复的装饰逻辑。

    建造者模式要求建造的过程必须是稳定的,而装饰模式的建造过程是不稳定的,可以有各种各样的组合方式。

    缺点:

 ADecoratorComponent不一样Decorator是一个透明的包装。如果从对象标识的观点出发,一个被装饰的组件与组件本身是有差别的,因此,使用装饰不应该依赖对象标识。

    B有许多小对象采用Decorator模式进行系统设计往往会产生许多类似的小对象,这些对象仅仅在他们相互连接的方式上有所不同,而不是它们的类或是它们的属性值有所不同。尽管对于那些了解这些系统的人来说,很容易对它们进行定制,但是很难学习这些系统,排错也很困难。

4、装饰模式使用场景

    装饰模式使用场景:

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

    B处理那些可以撤销的职责

    C当不能采用生成子类的方法扩充一种情况是可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

二、装饰模式实现

Component抽象类:

#ifndef COMPONENT_H#define COMPONENT_H#include 
using namespace std; //Component抽象类,定义类对象的接口class Component{public:    virtual ~Component(){}    virtual void Operation() = 0;protected:    Component(){}}; #endif // COMPONENT_H

ConcreteComponent具体对象类:

#ifndef CONCRETECOMPONENT_H#define CONCRETECOMPONENT_H#include "Component.h" //ConcreteComponent:具体的Component对象,可以给对象动态添加职责class ConcreteComponent : public Component{public:    ConcreteComponent(){}    ~ConcreteComponent(){}    virtual void Operation()    {        cout << "Original:ConcreteComponent::Operation" << endl;    }}; #endif // CONCRETECOMPONENT_H

Decorator抽象装饰对象类:

#ifndef DECORATOR_H#define DECORATOR_H#include "Component.h" //Decorator:装饰抽象类,继承自Componentclass Decorator : public Component{public:    Decorator(Component* com)    {        m_pCom = com;    }    void setComponent(Component* com)    {        m_pCom = com;    }    virtual ~Decorator(){}    virtual void Operation() = 0;protected:    Component* m_pCom;}; #endif // DECORATOR_H

ConcreteDecoratorA具体装饰对象类:

#ifndef CONCRETEDECORATORA_H#define CONCRETEDECORATORA_H#include "Decorator.h" //ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能class ConcreteDecoratorA : public Decorator{public:    ConcreteDecoratorA(Component* com):Decorator(com)    {    }    ~ConcreteDecoratorA(){}    virtual void Operation()    {        m_pCom->Operation();        //附加职责A        AddBehavorA();    }    void AddBehavorA()    {        cout << "Extra A:ConcreteDecoratorA::AddBehavorA" << endl;    }}; #endif // CONCRETEDECORATORA_H

ConcreteDecoratorB具体装饰对象类:

#ifndef CONCRETEDECORATORB_H#define CONCRETEDECORATORB_H#include "Decorator.h" //ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能class ConcreteDecoratorB : public Decorator{public:    ConcreteDecoratorB(Component* com):Decorator(com)    {}    ~ConcreteDecoratorB(){}    virtual void Operation()    {        m_pCom->Operation();        //附加职责B        AddBehavorB();    }    void AddBehavorB()    {        cout << "Extra B:ConcreteDecoratorB::AddBehavorB" << endl;    }}; #endif // CONCRETEDECORATORB_H

ConcreteDecoratorC具体装饰对象类:

#ifndef CONCRETEDECORATORC_H#define CONCRETEDECORATORC_H#include "Decorator.h" //ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能class ConcreteDecoratorC : public Decorator{public:    ConcreteDecoratorC(Component* com):Decorator(com)    {}    ~ConcreteDecoratorC(){}    virtual void Operation()    {        m_pCom->Operation();        //附加职责C        AddBehavorC();    }    void AddBehavorC()    {        cout << "Extra C:ConcreteDecoratorC::AddBehavorC" << endl;    }}; #endif // CONCRETEDECORATORC_H

ConcreteDecoratorD具体装饰对象类:

#ifndef CONCRETEDECORATORD_H#define CONCRETEDECORATORD_H#include "Decorator.h" //ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能class ConcreteDecoratorD : public Decorator{public:    ConcreteDecoratorD(Component* com):Decorator(com)    {}    ~ConcreteDecoratorD(){}    virtual void Operation()    {        m_pCom->Operation();        //附加职责D        AddBehavorD();    }    void AddBehavorD()    {        cout << "Extra D:ConcreteDecoratorD::AddBehavorD" << endl;    }}; #endif // CONCRETEDECORATORD_H

 

客户调用程序:

#include "ConcreteComponent.h"#include "ConcreteDecoratorA.h"#include "ConcreteDecoratorB.h"#include "ConcreteDecoratorC.h"#include "ConcreteDecoratorD.h" int main(){    //要装饰的对象    Component* pCom = new ConcreteComponent();    Decorator* pDec = NULL;     //给装饰对象附加职责A    pDec = new ConcreteDecoratorA(pCom);     //给装饰对象附加职责B    pDec = new ConcreteDecoratorB(pDec);     //给装饰对象附加职责C    pDec = new ConcreteDecoratorC(pDec);     //给装饰对象附加职责D    pDec = new ConcreteDecoratorD(pDec);    pDec->Operation();     delete pCom,pDec;    return 0;}

三、装饰模式实例

1、手机装饰实例

Phone抽象类:

#ifndef PHONE_H#define PHONE_H#include 
#include 
using namespace std; //抽象类class Phone{public:    Phone(){}    virtual ~Phone(){}    virtual void showDecorator() = 0;}; #endif // PHONE_H

iPhone具体对象类:

#ifndef IPHONE_H#define IPHONE_H#include "Phone.h" //具体手机类class iPhone : public Phone{public:    iPhone(string name):m_name(name){}    ~iPhone(){}    void showDecorator()    {        cout << m_name << " 's Decorator" << endl;    }private:    string m_name;}; #endif // IPHONE_H

MiPhone具体对象类:

#ifndef MIPHONE_H#define MIPHONE_H#include "Phone.h" //具体手机类class MiPhone : public Phone{public:    MiPhone(string name):m_name(name){}    ~MiPhone(){}    void showDecorator()    {        cout << m_name << " 's Decorator" << endl;    }private:    string m_name;}; #endif // MIPHONE_H

DecoratorPhone装饰基类:

#ifndef DECORATORPHONE_H#define DECORATORPHONE_H#include "Phone.h" //装饰基类class DecoratorPhone : public Phone{public:    DecoratorPhone(Phone* phone):m_phone(phone){}    ~DecoratorPhone(){}    virtual void showDecorator() = 0;protected:    Phone* m_phone;//要装饰的对象}; #endif // DECORATORPHONE_H

DecoratorPhoneA具体装饰对象类:

#ifndef DECORATORPHONEA_H#define DECORATORPHONEA_H#include "DecoratorPhone.h" //具体装饰类class DecoratorPhoneA : public DecoratorPhone{public:    DecoratorPhoneA(Phone* phone):DecoratorPhone(phone){}    void showDecorator()    {        m_phone->showDecorator();        addDecorator();//增加装饰    }private:    void addDecorator()    {        cout << "add a DecoratorPhoneA Decorator" << endl;    }}; #endif // DECORATORPHONEA_H

DecoratorPhoneB具体装饰对象类:

#ifndef DECORATORPHONEB_H#define DECORATORPHONEB_H#include "DecoratorPhone.h" //具体装饰类class DecoratorPhoneB : public DecoratorPhone{public:    DecoratorPhoneB(Phone* phone):DecoratorPhone(phone){}    void showDecorator()    {        m_phone->showDecorator();        addDecorator();//增加装饰    }private:    void addDecorator()    {        cout << "add a DecoratorPhoneB Decorator" << endl;    }}; #endif // DECORATORPHONEB_H

客户调用程序:

#include "Phone.h"#include "MiPhone.h"#include "iPhone.h"#include "DecoratorPhoneA.h"#include "DecoratorPhoneB.h" int main(){    Phone *iphone = new iPhone("iPhone X");    Phone* decorator1 = NULL;    decorator1 = new DecoratorPhoneA(iphone); //增加装饰    decorator1 = new DecoratorPhoneB(decorator1);    //增加装饰    decorator1->showDecorator();//显示装饰     Phone *mi = new MiPhone("Mi 6");    Phone* decorator2 = NULL;    decorator2 = new DecoratorPhoneA(mi); //增加装饰    decorator2 = new DecoratorPhoneB(decorator2);//增加装饰    decorator2->showDecorator();//显示装饰    delete decorator2,decorator2;    delete iphone,mi;    return 0;}