C++实现设计模式---装饰器模式 (Decorator)

装饰器模式 (Decorator)

装饰器模式 是一种结构型设计模式,它允许动态地将责任附加到对象上,既可以在运行时给一个对象添加功能,又不会影响其他对象的功能。


意图

  • 动态地扩展对象的功能。
  • 避免创建过多的子类,通过装饰器来"包装"对象,添加新功能。
  • 保持类的单一职责和开放封闭原则。

使用场景

  1. 系统需要动态地添加功能给对象
    • 如UI框架中的组件装饰,能动态增加功能(如窗口的滚动条、边框等)。
  2. 不希望通过继承来扩展对象功能
    • 继承可能会导致类的数量激增,装饰器模式能够解决这个问题。
  3. 功能扩展需要灵活控制
    • 可以在不同的对象上应用不同的装饰,不会互相影响。

参与者角色

  1. 组件接口 (Component)
    • 定义基本对象行为的接口,所有的装饰器和具体对象都需要实现此接口。
  2. 具体组件 (ConcreteComponent)
    • 具体实现基本行为的对象。
  3. 装饰器 (Decorator)
    • 持有组件的引用,并实现组件接口,增强功能。
  4. 具体装饰器 (ConcreteDecorator)
    • 通过调用被装饰对象的方法来添加额外功能。

示例代码

以下代码展示了如何使用装饰器模式扩展一个简单的咖啡类。

cpp 复制代码
#include <iostream>
#include <string>

// 组件接口
class Beverage {
public:
    virtual ~Beverage() = default;
    virtual std::string getDescription() const = 0;
    virtual double cost() const = 0;
};

// 具体组件:咖啡
class Coffee : public Beverage {
public:
    std::string getDescription() const override {
        return "Coffee";
    }

    double cost() const override {
        return 5.0;
    }
};

// 装饰器基类
class BeverageDecorator : public Beverage {
protected:
    Beverage* beverage;

public:
    BeverageDecorator(Beverage* b) : beverage(b) {}
    virtual ~BeverageDecorator() = default;
};

// 具体装饰器:加入牛奶
class MilkDecorator : public BeverageDecorator {
public:
    MilkDecorator(Beverage* b) : BeverageDecorator(b) {}

    std::string getDescription() const override {
        return beverage->getDescription() + ", Milk";
    }

    double cost() const override {
        return beverage->cost() + 1.0;
    }
};

// 具体装饰器:加入糖
class SugarDecorator : public BeverageDecorator {
public:
    SugarDecorator(Beverage* b) : BeverageDecorator(b) {}

    std::string getDescription() const override {
        return beverage->getDescription() + ", Sugar";
    }

    double cost() const override {
        return beverage->cost() + 0.5;
    }
};

// 客户端代码
int main() {
    Beverage* coffee = new Coffee();  // 创建基本的咖啡
    std::cout << coffee->getDescription() << " Cost: $" << coffee->cost() << std::endl;

    // 加入牛奶的装饰
    coffee = new MilkDecorator(coffee);
    std::cout << coffee->getDescription() << " Cost: $" << coffee->cost() << std::endl;

    // 再加入糖的装饰
    coffee = new SugarDecorator(coffee);
    std::cout << coffee->getDescription() << " Cost: $" << coffee->cost() << std::endl;

    // 清理内存
    delete coffee;

    return 0;
}

代码解析

1. 组件接口

  • Beverage 类是所有具体组件和装饰器的公共接口,定义了所有具体对象的行为:
cpp 复制代码
class Beverage {
public:
    virtual ~Beverage() = default;
    virtual std::string getDescription() const = 0;
    virtual double cost() const = 0;
};

2. 具体组件

  • Coffee 是具体的组件,提供了描述和计算费用的功能:
cpp 复制代码
class Coffee : public Beverage {
public:
    std::string getDescription() const override {
        return "Coffee";
    }

    double cost() const override {
        return 5.0;
    }
};

3. 装饰器基类

  • BeverageDecorator 继承了 Beverage,并持有一个 Beverage 对象,能够动态地扩展其功能:
cpp 复制代码
class BeverageDecorator : public Beverage {
protected:
    Beverage* beverage;

public:
    BeverageDecorator(Beverage* b) : beverage(b) {}
    virtual ~BeverageDecorator() = default;
};

4. 具体装饰器

  • MilkDecoratorSugarDecorator 是具体的装饰器类,分别增加了 MilkSugar 的功能:
cpp 复制代码
class MilkDecorator : public BeverageDecorator {
public:
    MilkDecorator(Beverage* b) : BeverageDecorator(b) {}

    std::string getDescription() const override {
        return beverage->getDescription() + ", Milk";
    }

    double cost() const override {
        return beverage->cost() + 1.0;
    }
};
cpp 复制代码
class SugarDecorator : public BeverageDecorator {
public:
    SugarDecorator(Beverage* b) : BeverageDecorator(b) {}

    std::string getDescription() const override {
        return beverage->getDescription() + ", Sugar";
    }

    double cost() const override {
        return beverage->cost() + 0.5;
    }
};

5. 客户端

  • 客户端可以按需为原始对象添加装饰,每次调用 getDescriptioncost 时,都能看到新添加的功能:
cpp 复制代码
int main() {
    Beverage* coffee = new Coffee();  
    std::cout << coffee->getDescription() << " Cost: $" << coffee->cost() << std::endl;

    coffee = new MilkDecorator(coffee);
    std::cout << coffee->getDescription() << " Cost: $" << coffee->cost() << std::endl;

    coffee = new SugarDecorator(coffee);
    std::cout << coffee->getDescription() << " Cost: $" << coffee->cost() << std::endl;

    delete coffee;
    return 0;
}

优缺点

优点

  1. 动态扩展功能
    • 可以在运行时为对象添加新功能。
  2. 避免子类数量暴增
    • 通过装饰器而不是继承来扩展功能,避免了类的膨胀。
  3. 高灵活性
    • 可以灵活地为不同的对象选择不同的装饰器进行组合。

缺点

  1. 增加系统复杂性
    • 过多的装饰器可能使系统变得复杂,难以理解。
  2. 装饰器的顺序问题
    • 装饰器的顺序会影响最终对象的行为。

适用场景

  • 动态地给一个对象添加功能,例如为一个对象添加不同的用户界面样式、不同的服务功能。
  • 避免使用继承,需要在运行时动态地扩展功能。

总结

装饰器模式是一种非常灵活的模式,能够动态地给对象添加新功能,避免了继承带来的问题。通过组合装饰器类,能够灵活地为对象组合不同的功能,在很多场景中非常有用。


相关推荐
在未来等你4 小时前
AI Agent设计模式 Day 19:Feedback-Loop模式:反馈循环与自我优化
设计模式·llm·react·ai agent·plan-and-execute
凌康ACG5 小时前
Sciter之c++与前端交互(五)
c++·sciter
郝学胜-神的一滴7 小时前
Linux命名管道:创建与原理详解
linux·运维·服务器·开发语言·c++·程序人生·个人开发
晚风(●•σ )7 小时前
C++语言程序设计——11 C语言风格输入/输出函数
c语言·开发语言·c++
恒者走天下8 小时前
秋招落定,拿到满意的offer,怎么提高自己实际的开发能力,更好的融入团队
c++
兵bing9 小时前
设计模式-访问者模式
设计模式·访问者模式
python零基础入门小白9 小时前
【万字长文】大模型应用开发:意图路由与查询重写设计模式(从入门到精通)
java·开发语言·设计模式·语言模型·架构·大模型应用开发·大模型学习
天若有情6739 小时前
【c++】手撸C++ Promise:从零实现通用异步回调组件,支持链式调用+异常安全
开发语言·前端·javascript·c++·promise
学困昇9 小时前
C++中的异常
android·java·c++
MC丶科9 小时前
Java设计模式漫画英雄宇宙-工厂模式 —Factory博士的“超级英雄制造机”!
java·设计模式·漫画