设计模式C++装饰

设计模式C++装饰

参考视频:【设计模式(完整版)】2.4装饰_哔哩哔哩_bilibili

分类:(对象)结构型

问题:饮料店订单系统,饮料有多种,并且可以选择加牛奶,冰激凌,巧克力等配料.

解决方案:动态地给一个对象添加一些额外的职责.就增加功能来说,装饰模式相比生成子类更加灵活.找出基本组件和可选层次.

1.组件(Component)声明封装器和被封装对象的共用接口.

2.具体组件(Concrete Component)类是被封装对象所属的类.它定义了基础行为,但装饰类可以改变这些行为.

3.基础装饰(Base Decorator)类拥有指向被封装对象的引用成员变量.装饰基类会将所有操作委派给被封装的对象.

4.具体装饰类(Concrete Decorators)定义了可动态添加到组件的额外行为.具体装饰类会重写装饰基类的方法,并在调用父类方法之前或之后进行额外的行为.

5.客户端(Client)可以使用多层装饰来封装部件,只要它能使用通用接口与所有的对象互动即可.

再看一个例子,使用装饰模式能够对敏感数据进行压缩和加密:

优点:

无需创建子类即可拓展对象的行为.

可以在运行时添加或删除对象的功能.

可以用多个装饰封装对象来组合几种行为.

单一职责原则.将实现了许多不同行为的大类拆分为多个较小的类.

缺点:

在封装器栈中删除特定封装器比较困难.

实现行为不受装饰栈顺序影响的装饰比较困难.

各层的初始化配置代码看上去可能会很糟糕.

代码:

#include <iostream>
#include <string>
​
//接口:具体被包裹的类,以及装饰类
class Beverage
{
public:
    virtual ~Beverage() {}
    virtual std::string Operation() const = 0;
​
};
//具体的被装饰者
class Americano :public Beverage
{
public:
    ~Americano() {}
    std::string Operation() const override
    {
        return "美式咖啡";
    }
};
//装饰
//基础部分(可能包括额外部分)
class Ingredient :public Beverage
{
protected:
    Beverage* m_beverage;
public:
    ~Ingredient() {};
    Ingredient(Beverage* beverage) :m_beverage(beverage) {}
    std::string Operation() const override
    {
        //核心代码,不是被用来被基类覆盖的
        return m_beverage->Operation();
    }
};
//额外部分(需要委托基类完成基础部分)不能直接继承Beverage
class Whip :public Ingredient
{
public:
    ~Whip() {}
    Whip(Beverage* beverage) :Ingredient(beverage)
    {
​
    }
    std::string Operation() const override
    {
        //在基类的Operation之前,之后都可以增加额外的操作
        return "奶昔("+Ingredient::Operation()+")";
    }
};
​
class Mocha :public Ingredient
{
public:
    ~Mocha() {}
    Mocha(Beverage* beverage) :Ingredient(beverage)
    {
​
    }
    std::string Operation() const override
    {
        //在基类的Operation之前,之后都可以增加额外的操作
        return "摩卡(" + Ingredient::Operation() + ")";
    }
};
​
void ClientCode(Beverage* beverage)
{
    std::cout << "执行结果:" << beverage->Operation();
}
int main()
{
    std::cout << "来一杯普通美式咖啡" << std::endl;
    Beverage* americano = new Americano();
    ClientCode(americano);
    std::cout << std::endl;
​
    std::cout << "来一杯双份摩卡+奶昔的美式咖啡" << std::endl;
    Beverage* whip1 = new Whip(americano);
    Beverage* mocha1 = new Mocha(whip1);
    Beverage* mocha2 = new Mocha(mocha1);
    ClientCode(mocha2);
​
    delete americano;
    delete whip1;
    delete mocha1;
    delete mocha2;
}
  • 30
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值