C++ 装饰器模式

装饰器模式(Decorator Pattern)是一种结构型设计模式,允许在不修改对象代码的情况下,动态为对象添加新功能。通过将对象包装在装饰器类中实现,遵循开放-封闭原则(对扩展开放,对修改封闭)。

  • 适用场景
    • 动态扩展对象功能(如为咖啡加配料、为函数加日志)。
    • 需要组合多种功能。
  • 核心组件
    • 抽象组件:定义接口。
    • 具体组件:被装饰的原始对象。
    • 抽象装饰器:持有一个组件对象,扩展接口。
    • 具体装饰器:实现具体功能的扩展。

📝 C++11 实现示例

以下是一个咖啡店订单系统示例,展示如何用装饰器模式为咖啡动态添加牛奶和糖。

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

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

// 具体组件:基础咖啡
class SimpleCoffee : public Coffee {
public:
    std::string getDescription() const override { return "Simple Coffee"; }
    double cost() const override { return 1.0; }
};

// 抽象装饰器
class CoffeeDecorator : public Coffee {
protected:
    std::unique_ptr<Coffee> coffee_;
public:
    explicit CoffeeDecorator(std::unique_ptr<Coffee> coffee) : coffee_(std::move(coffee)) {}
    std::string getDescription() const override { return coffee_->getDescription(); }
    double cost() const override { return coffee_->cost(); }
};

// 具体装饰器:加牛奶
class MilkDecorator : public CoffeeDecorator {
public:
    explicit MilkDecorator(std::unique_ptr<Coffee> coffee) : CoffeeDecorator(std::move(coffee)) {}
    std::string getDescription() const override { return coffee_->getDescription() + ", Milk"; }
    double cost() const override { return coffee_->cost() + 0.5; }
};

// 具体装饰器:加糖
class SugarDecorator : public CoffeeDecorator {
public:
    explicit SugarDecorator(std::unique_ptr<Coffee> coffee) : CoffeeDecorator(std::move(coffee)) {}
    std::string getDescription() const override { return coffee_->getDescription() + ", Sugar"; }
    double cost() const override { return coffee_->cost() + 0.3; }
};

// 测试
int main() {
    auto coffee = std::make_unique<SimpleCoffee>();
    std::cout << coffee->getDescription() << ": $" << coffee->cost() << '\n';

    coffee = std::make_unique<MilkDecorator>(std::move(coffee));
    std::cout << coffee->getDescription() << ": $" << coffee->cost() << '\n';

    coffee = std::make_unique<SugarDecorator>(std::move(coffee));
    std::cout << coffee->getDescription() << ": $" << coffee->cost() << '\n';

    return 0;
}

输出

复制代码
Simple Coffee: $1
Simple Coffee, Milk: $1.5
Simple Coffee, Milk, Sugar: $1.8

🔍 代码解析

  • 接口(Coffee) :定义getDescriptioncost方法。
  • 基础对象(SimpleCoffee):实现基本咖啡功能。
  • 装饰器(CoffeeDecorator) :通过std::unique_ptr持有Coffee对象,支持递归包装。
  • 具体装饰器(MilkDecorator, SugarDecorator):扩展描述和价格。
  • C++11特性
    • std::unique_ptr:管理内存,防止泄漏。
    • std::move:优化对象传递。
    • override:确保虚函数正确重写。

✅ 优点

  • 灵活性:运行时动态添加功能。
  • 可扩展:易于新增装饰器(如加巧克力)。
  • 单一职责:每个装饰器只负责一种功能。

⚠️ 缺点

  • 多层装饰可能增加代码复杂性。
  • 可能有轻微性能开销(调用链)。

🛠️ 注意事项

  • 确保组件和装饰器接口一致。
  • 避免过度装饰,保持代码清晰。
  • C++装饰器模式基于类的组合,与Python的函数装饰器(基于闭包)不同。

🌟 其他应用场景

  • 日志系统:为函数添加日志。
  • 权限控制:为操作添加权限检查。
  • 数据流:为I/O流添加加密、压缩等功能。
相关推荐
汉克老师3 小时前
CSP-J 2026 初赛试题解析(第一部分:选择题(8-15))精讲
c++·csp-j·小学生·学c++编程
wabs6663 小时前
关于二叉树【力扣572.另一棵树的子树的思考】
数据结构·c++·算法·leetcode·二叉树
风合星语4 小时前
2026 ROS 2 Lyrical C++ 入门(五):Action 实战——任务反馈、取消与超时处理
c++·机器人·ros2·异步编程·lyrical
91刘仁德5 小时前
C++ 继承和多态 设计模式
c语言·c++·笔记
库玛西5 小时前
哈夫曼树与前缀编码:数据压缩的贪心核心
c语言·c++·笔记·考研
别动我齐刘海6 小时前
ROS2 Jazzy + C++ 实战路线——进阶学习3
c++·人工智能·vscode·python·算法·机器学习·机器人
0+1116 小时前
算法 --滑动窗口
c++·算法·leetcode
stolentime6 小时前
(有原题)CSP-S2026第一轮试题(附答案解析、markdown源码)
c++·csp
m0_734571766 小时前
深入理解C++ RAII
开发语言·c++
hetao17338376 小时前
2026-09-18 hetao1733837 的刷题记录
c++·算法