装饰模式

时常会遇到这样一种情况,我已经设计好了一个接口,并且也有几个实现类,但是这时我发现我设计的时候疏忽了,忘记了一些功能,或者后来需求变动要求加入一些功能,最简单的做法就是修改接口,添加函数,然后继承类中都相应的添加实现,这样做倒也没什么问题,但是如果这种变化来个好几次或者继承类非常多,那工作量可就大了。

这时大神们就发明了装饰模式,在不修改现有接口和实现类的基础上实现功能或者状态的添加。装饰器模式是一种用于代替继承的技术,无需通过继承增加子类就能扩展对象的新功能。使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。

适用性:

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

       2、处理那些可以撤销的职责。

       3、希望为某个对象而不是一整个类添加一些功能时。

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

效果:

       1、比静态继承更为灵活。继承机制会产生许多新类,增加了系统的复杂度。而装饰可以使你对一些职责进行混合和匹配。

       2、避免在层次结构高层的类有太多的特征。扩展一个复杂类的时候,很可能会暴露出与添加职责无关的细节。你可以定义一个简单的类,并且用装饰逐渐的添加功能。

       3、会产生许多小对象

       4、Decorator与Component不一样,Decorator是一个透明的包装。如果我们从对象标识的观点出发,一个被装饰了的组件与这个组件是有差别的,因此,使用装饰时不应该依赖对象标识。

注意:

       1、接口的一致性。装饰对象的接口必须与它所装饰的Component的接口是一致的。

       2、省略抽象的Docorator类。当你仅需要添加一个职责的时,没有必要定义抽象Decorator类。你常常需要处理显存的类层次结构而不是设计一个新系统,这时你可以把Decorator向Component转发请求的职责合并到ConcreteDecorator中。

       3、保持Component类的简单性。为了保证接口的一致性,组件和装饰必须有一个共同的Component父类。因此保持这个类的简单些是很重要的。

参与者:

Component

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

ConcreteComponent

——定义一个对象,可以给这个对象添加一些职责。

Decorator

——维持一个指向Component对象的指针,并定义一个与Component接口一致的接口。

ConcreteDecorator

——向组件添加职责

UML:

 


#include <iostream>
using namespace std;

class Component
{
public:
    Component(){}
    virtual ~Component(){}

    virtual void operation() = 0;
};


class ConcreteComponent: public Component
{
public:
    ConcreteComponent(){}
    ~ConcreteComponent(){}

    void operation()
    {
        cout<<"ConcreteComponent's operation"<<endl;
    }
};

class Decorator: public Component
{
public:
    Decorator(){}
    virtual ~Decorator(){}

    virtual void operation()
    {
        if(mComponent)
            mComponent->operation();
    }
    virtual void setComponent(Component* pComponent)
    {
        mComponent=pComponent;
    }

protected:
    Component* mComponent;
};

class ConcreteDecoratorA: public Decorator
{
private:
    string addState;
public:
    ConcreteDecoratorA(){}
    virtual ~ConcreteDecoratorA(){}
    void operation()
    {
        Decorator::operation();
        addState="new state";
        cout<<"ConcreteDecoratorA's operation"<<endl;
    }
};
class ConcreteDecoratorB: public Decorator
{
public:
    ConcreteDecoratorB(){}
    virtual ~ConcreteDecoratorB(){}
    void operation()
    {
        Decorator::operation();
        addBehavior();
        cout<<"ConcreteDecoratorB's operation"<<endl;
    }
    void addBehavior()
    {
        cout<<"ConcreteDecoratorB's addBehavior"<<endl;
    }
};

int main()
{
    Component* pComponent = new ConcreteComponent();
    ConcreteDecoratorA* pA = new ConcreteDecoratorA();
    ConcreteDecoratorB* pB = new ConcreteDecoratorB();
    pA->setComponent(pComponent);//ConcreteDecoratorA对象pA包装pComponent
    pB->setComponent(pA);//ConcreteDecoratorB对象pB包装pA
    pB->operation();//执行pB的operation
    return 0;
}

通过setComponent来将对象进行包装。每个装饰对象的实现和如何使用这个对象分离开了,每个装饰对象只关心自己的功能,不需要关心如何被添加到对象链当中

装饰模式是为已有功能动态添加更多功能的一种方式。把类中的装饰功能从类中搬移去除,简化了原有的类,有效的把类的核心职责和装饰功能区分开,而且可以去除相关类中重复的装饰逻辑

例:

比如有一个手机,允许你为手机添加特性,比如增加挂件、屏幕贴膜等。一种灵活的设计方式是,将手机嵌入到另一对象中,由这个对象完成特性的添加,我们称这个嵌入的对象为装饰。这个装饰与它所装饰的组件接口一致,因此它对使用该组件的客户透明。下面给出装饰模式的UML图。


#include <iostream>
using namespace std;
//公共抽象类
class Phone
{
public:
	Phone() {}
	virtual ~Phone() {}
	virtual void ShowDecorate() {}
};

//具体的手机类
class iPhone : public Phone
{
private:
	string m_name; //手机名称
public:
	iPhone(string name): m_name(name){}
	~iPhone() {}
	void ShowDecorate()
	{
	    cout<<m_name<<"的装饰"<<endl;
    }
};
//具体的手机类
class NokiaPhone : public Phone
{
private:
	string m_name;
public:
	NokiaPhone(string name): m_name(name){}
	~NokiaPhone() {}
	void ShowDecorate()
	{
	    cout<<m_name<<"的装饰"<<endl;
    }
};

//装饰类
class DecoratorPhone : public Phone
{
private:
	Phone *m_phone;  //要装饰的手机
public:
	DecoratorPhone(Phone *phone): m_phone(phone) {}
	virtual void ShowDecorate()
	{
	    m_phone->ShowDecorate();
    }
};
//具体的装饰类
class DecoratorPhoneA : public DecoratorPhone
{
public:
	DecoratorPhoneA(Phone *phone) : DecoratorPhone(phone) {}
	void ShowDecorate()
	{
	    DecoratorPhone::ShowDecorate();
	    AddDecorate();
    }
private:
	void AddDecorate() { cout<<"增加挂件"<<endl; } //增加的装饰
};
//具体的装饰类
class DecoratorPhoneB : public DecoratorPhone
{
public:
	DecoratorPhoneB(Phone *phone) : DecoratorPhone(phone) {}
	void ShowDecorate()
	{
	    DecoratorPhone::ShowDecorate();
	    AddDecorate();
    }
private:
	void AddDecorate() { cout<<"屏幕贴膜"<<endl; } //增加的装饰
};

int main()
{
	Phone *iphone = new NokiaPhone("6300");
	Phone *dpa = new DecoratorPhoneA(iphone); //装饰,增加挂件
	Phone *dpb = new DecoratorPhoneB(dpa);    //装饰,屏幕贴膜
	dpb->ShowDecorate();
	delete dpa;
	delete dpb;
	delete iphone;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值