设计模式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;
}

相关推荐

  1. 设计模式装饰模式 -- C++】

    2024-02-04 16:24:02       54 阅读
  2. C++设计模式装饰模式

    2024-02-04 16:24:02       23 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-04 16:24:02       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-04 16:24:02       106 阅读
  3. 在Django里面运行非项目文件

    2024-02-04 16:24:02       87 阅读
  4. Python语言-面向对象

    2024-02-04 16:24:02       96 阅读

热门阅读

  1. 计算机系统的一些概念

    2024-02-04 16:24:02       65 阅读
  2. AM波的调制与解调

    2024-02-04 16:24:02       51 阅读
  3. SSRF笔记整理

    2024-02-04 16:24:02       46 阅读
  4. 服务器安装docker环境

    2024-02-04 16:24:02       45 阅读
  5. sql求中位数

    2024-02-04 16:24:02       57 阅读
  6. LeetCode803. Bricks Falling When Hit——洪水填充

    2024-02-04 16:24:02       47 阅读
  7. vue中$refs的用法及作用详解

    2024-02-04 16:24:02       45 阅读
  8. C# 从“byte[]”转换为“BitmapImage”

    2024-02-04 16:24:02       58 阅读
  9. openEuler 22.03 docker安装elasticsearch 7.17.17

    2024-02-04 16:24:02       41 阅读
  10. 美敦力呼吸机PB560硬件分析

    2024-02-04 16:24:02       56 阅读
  11. [C语言]结构体初识

    2024-02-04 16:24:02       56 阅读