C++设计模式整理010-装饰者模式

装饰模式是一种设计模式,用于在运行时给对象添加额外功能,而不修改其原有结构。通过创建包装对象,装饰者模式实现了功能的动态添加和撤销。在汽车配置和手机装饰的实例中,展示了如何使用装饰模式来灵活地组合不同组件,如添加LED、安装PC或电子驻车制动系统。这种模式在需要扩展功能时比继承更灵活,尤其适用于大量独立扩展的情况。

目录

15. 装饰模式

15.1 实例2

15.2 实例3


15. 装饰模式

        装饰模式:动态地给一个对象添加一些额外的功能,它是通过创建一个包装对象,也就是装饰来包裹真实的对象。新增加功能来说,装饰器模式比生产子类更加灵活。

        以下情形考虑使用装饰模式:

                1. 需要扩展一个类的功能,或给一个类添加附加职责。

                2. 需要动态的给一个对象添加功能,这些功能可以再动态的撤销。

                3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。

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

/*
 * 关键代码:1、Component 类充当抽象角色,不应该具体实现。 2、修饰类引用和继承 Component 类,具体扩展类重写父类方法。
 */
#include <iostream>

using namespace std;

//抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。
class Component
{
public:
    virtual ~Component(){}

    virtual void configuration() = 0;
};

//具体构件(Concrete Component)角色:定义一个将要接收附加责任的类。
class Car : public Component
{
public:
    void configuration() override
    {
        cout << "A Car" << endl;
    }
};

//装饰(Decorator)角色:持有一个构件(Component)对象的实例,并实现一个与抽象构件接口一致的接口。
class DecorateCar : public Component
{
public:
    DecorateCar(Component* car) : m_pCar(car){}

    void configuration() override
    {
        m_pCar->configuration();
    }

private:
    Component* m_pCar;
};

//具体装饰(Concrete Decorator)角色:负责给构件对象添加上附加的责任。
class DecorateLED : public DecorateCar
{
public:
    DecorateLED(Component* car) : DecorateCar(car){}

    void configuration() override
    {
        DecorateCar::configuration();
        addLED();
   }

private:
    void addLED()
    {
        cout << "Install LED" << endl;
    }

};

//具体装饰(Concrete Decorator)角色:负责给构件对象添加上附加的责任。
class DecoratePC : public DecorateCar
{
public:
    DecoratePC(Component* car) : DecorateCar(car){}

    void configuration() override
    {
        DecorateCar::configuration();
        addPC();
    }

private:
    void addPC()
    {
        cout << "Install PC" << endl;
    }
};

//具体装饰(Concrete Decorator)角色:负责给构件对象添加上附加的责任。
class DecorateEPB : public DecorateCar
{
public:
    DecorateEPB(Component* car) : DecorateCar(car){}

    void configuration() override
    {
        DecorateCar::configuration();
        addEPB();
    }

private:
    void addEPB()
    {
        cout << "Install Electrical Park Brake" << endl;
    }
};

int main()
{
    Car* car = new Car;
    DecorateLED* ledCar = new DecorateLED(car);
    DecoratePC* pcCar = new DecoratePC(ledCar);
    DecorateEPB* epbCar = new DecorateEPB(pcCar);

    epbCar->configuration();

    delete epbCar;
    epbCar = nullptr;

    delete pcCar;
    pcCar = nullptr;

    delete ledCar;
    ledCar = nullptr;

    delete car;
    car = nullptr;

    return 0;
}

15.1 实例2

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

        有时我们希望给某个对象而不是整个类添加一些功能。

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

 

        在这种设计中,手机的装饰功能被独立出来,可以单独发展,进而简化了具体手机类的设计。下面给出Phone类的实现:

//公共抽象类
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;
}

        装饰模式提供了更加灵活的向对象添加职责的方式。可以用添加和分离的方法,用装饰在运行时刻增加和删除职责。装饰模式提供了一种“即用即付”的方法来添加职责。它并不试图在一个复杂的可定制的类中支持所有可预见的特征,相反,你可以定义一个简单的类,并且用装饰类给它逐渐地添加功能。可以从简单的部件组合出复杂的功能。[DP]

        在本文的例子中,我们定义了两个具体的手机类,iPhone类和NokiaPhone类,通过单独的装饰类为它们添加特性,从而组合出复杂的功能。

 

15.2 实例3

       比如:咖啡店。

       有个组件:

              提供接口—计算费用。

       咖啡 : 组件

              基类咖啡;

              派生出:磨铁咖啡,美式咖啡等等。

       装饰物 : 组件

              牛奶;

              抹茶;

              …;

       当用户点餐时,先选定一个咖啡A,然后选择加料A,料B,不断用装饰物去装饰咖啡。最后调用接口--计算费用。即可以得到(咖啡A + 料A + 料B + …)的价格。

 

参考资料:https://blog.youkuaiyun.com/wuzhekai1985/article/details/6672614

参考资料:https://www.cnblogs.com/chengjundu/p/8473564.html

参考资料:《Head First 设计模式》

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

公众号:程序喵星人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值