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流添加加密、压缩等功能。
相关推荐
威桑4 小时前
LLVM (Low Level Virtual Machine)全景机制解析
c++·gcc·llvm
一只小bit5 小时前
Qt 快速开始:安装配置并创建简单标签展示
开发语言·前端·c++·qt·cpp
雍凉明月夜6 小时前
c++ 精学笔记记录Ⅰ
开发语言·c++·笔记
小鹏编程6 小时前
C++ 周期问题 - 计算n天后星期几
开发语言·c++
繁华似锦respect6 小时前
C++ unordered_map 底层实现与详细使用指南
linux·开发语言·c++·网络协议·设计模式·哈希算法·散列表
稚辉君.MCA_P8_Java6 小时前
Gemini永久会员 C++返回最长有效子串长度
开发语言·数据结构·c++·后端·算法
ULTRA??7 小时前
Qt 数据类型体系(AI总结)
c++·qt
zmzb01037 小时前
C++课后习题训练记录Day42
开发语言·c++·算法
QQ_4376643147 小时前
线程池设计与实现
c++
ULTRA??8 小时前
ROS Action 完整示例(AI辅助):客户端发目标 + 服务器接参数(lambda 替代 boost::bind)
c++·python