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

✅ 优点

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

⚠️ 缺点

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

🛠️ 注意事项

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

🌟 其他应用场景

  • 日志系统:为函数添加日志。
  • 权限控制:为操作添加权限检查。
  • 数据流:为I/O流添加加密、压缩等功能。
相关推荐
aqiu1111117 小时前
【C++算法打怪专栏】8. 字符串转换整数 (atoi)
开发语言·c++·算法
h397412 小时前
DirectShow过滤器开发-视频源过滤器
c++·windows·音视频·directshow
程序猿编码14 小时前
榨干 RTX5090 算力!Qwen3 专用单卡推理引擎,手写C++/CUDA 算子实现 MTP 推测解码
开发语言·c++·大模型推理·qwen3·多模态推理
西飘客14 小时前
vs 怎么根据dll 生成lib文件
c++·qt
程序员老陆15 小时前
深入理解 C++ thread_local:线程私有存储的正确打开方式
开发语言·c++·程序设计
半杯咖啡半行码19 小时前
C++ 编程与 STL 模板:从泛型编程到内存安全详解
开发语言·c++
xh didida20 小时前
Linux -- 基础IO
linux·服务器·开发语言·c++
垆边人似月.20 小时前
华为机试题 :两数之和
c++·算法·华为
个 人 练 习 生20 小时前
C++ string 类模拟实现:从底层理解字符串(上)
开发语言·c++·经验分享·学习·程序人生
垆边人似月.20 小时前
华为机试题 :有效的括号
c++·算法·华为