• 【C++设计模式之装饰模式:结构型】分析及示例


    装饰模式(Decorator Pattern)是一种结构型设计模式,它允许在运行时动态地给一个对象添加额外的行为。

    描述

    装饰模式通过创建一个包装器(Wrapper)来包裹原始对象,并在原始对象的行为前后添加额外的功能。通过这种方式,可以实现在不改变原始对象结构的情况下,动态地给对象添加新的功能。

    原理

    装饰模式的核心思想是使用继承和组合。创建一个装饰器类,它继承自原始对象所属的抽象类或接口,并且内部持有一个原始对象的引用。装饰器类通过重写原始对象的方法,并在方法的前后添加额外的行为逻辑。

    类图

    在这里插入图片描述
    其中的各个类的作用如下:

    抽象组件(Component): 可以是接口或者抽象类,它定义了具体类以及装饰器所拥有的方法。
    具体组件(ComponentA, ComponentB):具体的组件,实现或者继承自抽象组件。可以理解成上述场景中已存在的类。
    抽象装饰器(Decorator):通常为抽象类,持有一个被装饰的对象,定义了具体装饰器的方法。此类非必须也可以没有,具体装饰器也可直接继承或者实现抽象组件。
    具体装饰器(DecoratorX, DecoratorY):具体的装饰器,继承自抽象装饰器(也可直接继承自抽象组件),扩展了抽象组件的某些功能。

    示例

    假设有一个咖啡店,咖啡有不同种类(如浓缩咖啡、美式咖啡)和不同口味的添加物(如牛奶、糖)。希望能够动态地给咖啡添加不同的口味,而不需要修改咖啡类的代码。

    首先,定义一个咖啡的抽象类(Coffee),其中包含一个获取描述的方法(getDescription)和获取价格的方法(getPrice)。
    然后,创建具体的咖啡类(Espresso、Americano),它们各自实现了抽象类的方法。
    接下来,创建一个装饰器类(CoffeeDecorator),它也继承自咖啡的抽象类,并持有一个咖啡对象的引用。
    装饰器类可以通过重写抽象类的方法,在方法的前后添加额外的行为。

    C++示例代码如下:

    // 咖啡抽象类
    class Coffee {
    public:
        virtual string getDescription() = 0;
        virtual double getPrice() = 0;
    // 浓缩咖啡
    class Espresso : public Coffee {
    public:
        string getDescription() override {
            return "Espresso";
        }
    
        double getPrice() override {
            return 1.99;
        }
    };
    
    // 美式咖啡
    class Americano : public Coffee {
    public:
        string getDescription() override {
            return "Americano";
        }
    
        double getPrice() override {
            return 2.39;
        }
    };
    
    // 咖啡装饰器类
    class CoffeeDecorator : public Coffee {
    protected:
        Coffee* coffee;
    
    public:
        CoffeeDecorator(Coffee* coffee) : coffee(coffee) {}
    
        string getDescription() override {
            return coffee->getDescription();
        }
    
        double getPrice() override {
            return coffee->getPrice();
        }
    };
    
    // 牛奶装饰器
    class MilkDecorator : public CoffeeDecorator {
    public:
        MilkDecorator(Coffee* coffee) : CoffeeDecorator(coffee) {}
    
        string getDescription() override {
            return coffee->getDescription() + ", Milk";
        }
    
        double getPrice() override {
            return coffee->getPrice() + 0.5;
        }
    };
    
    // 糖装饰器
    class SugarDecorator : public CoffeeDecorator {
    public:
        SugarDecorator(Coffee* coffee) : CoffeeDecorator(coffee) {}
    
        string getDescription() override {
            return coffee->getDescription() + ", Sugar";
        }
    
        double getPrice() override {
            return coffee->getPrice() + 0.3;
        }
    };
    
    // 使用示例
    int main() {
        Coffee* espresso = new Espresso();
        cout << "Description: " << espresso->getDescription() << endl;
        cout << "Price: $" << espresso->getPrice() << endl;
    
        Coffee* espressoWithMilk = new MilkDecorator(espresso);
        cout << "Description: " << espressoWithMilk->getDescription() << endl;
        cout << "Price: $" << espressoWithMilk->getPrice() << endl;
    
        delete espresso;
        espresso = 0;
        delete espressoWithMilk;
        espressoWithMilk = 0;
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91

    输出结果

    Description: Espresso
    Price: $1.99
    Description: Espresso, Milk
    Price: $2.49
    首先,输出浓缩咖啡(Espresso)的描述为"Espresso",价格为$1.99。
    然后,输出牛奶装饰器(MilkDecorator)装饰后的浓缩咖啡的描述为"Espresso, Milk",价格为$2.49
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    解释

    在上述示例中,定义了咖啡的抽象类(Coffee),并创建了具体的浓缩咖啡类(Espresso)和美式咖啡类(Americano)。
    然后,创建了一个咖啡装饰器类(CoffeeDecorator),它继承自咖啡的抽象类,并持有一个咖啡对象的引用。
    进一步,创建了具体的装饰器类,如牛奶装饰器(MilkDecorator)和糖装饰器(SugarDecorator),它们分别继承自咖啡装饰器类。

    在示例中,首先创建了一个浓缩咖啡对象,并输出其描述和价格。
    然后,用牛奶装饰器(MilkDecorator)装饰该浓缩咖啡对象,再次输出描述和价格。
    可以看到,装饰器类在不改变原始咖啡对象的情况下,给其添加了额外的行为。

    结论

    装饰模式通过包装原始对象,在不改变其结构的前提下,动态地给对象添加额外的功能。这样可以实现代码的易扩展性和灵活性。

    应用场景

    装饰模式适用于以下情况:

    1. 当需要给一个对象动态地添加额外的行为时;
    2. 当需要在不改变对象结构的情况下,对对象的某些行为进行扩展;
    3. 当不适合使用继承来扩展对象功能时。

    装饰模式可以应用于各种场景,如日志记录、权限验证、性能监控等。它可以灵活地给对象添加多个装饰器,实现各种组合效果,且与原始对象无关。

  • 相关阅读:
    MEV进入比特币,它将改变比特币挖矿?
    Quick Pow: 如何快速求幂
    pytorch加载darknet权重文件
    HTTP状态码
    SpringBoot_11_整合MyBatis
    npm和yarn的一些命令
    Oracle中计算除法——解决除数为零报错
    当我看源码的时候,我在想什么?
    自制手机app的51蓝牙+循迹+OLED显示速度小车
    BCH编码译码误码率性能matlab仿真
  • 原文地址:https://blog.csdn.net/MrHHHHHH/article/details/133589778