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流添加加密、压缩等功能。
相关推荐
Meteors.17 小时前
23种设计模式——中介者模式 (Mediator Pattern)详解
java·设计模式·中介者模式
Dream it possible!17 小时前
LeetCode 面试经典 150_栈_简化路径(53_71_C++_中等)(栈+stringstream)
c++·leetcode·面试·
爱和冰阔落17 小时前
【C++继承下】继承与友元 / static 菱形继承与虚继承 组合的详解分析
c++·面试·腾讯云ai代码助手
草莓熊Lotso18 小时前
《C++ Stack 与 Queue 完全使用指南:基础操作 + 经典场景 + 实战习题》
开发语言·c++·算法
敲上瘾18 小时前
单序列和双序列问题——动态规划
c++·算法·动态规划
ajassi200018 小时前
开源 C++ QT QML 开发(二十二)多媒体--ffmpeg编码和录像
c++·qt·开源
Query*18 小时前
Java 设计模式——适配器模式:从原理到3种实战的完整指南
java·设计模式·适配器模式
Meteors.18 小时前
23种设计模式——状态模式(State Pattern)
java·设计模式·状态模式
星星点点洲20 小时前
PostgreSQL 15二进制文件
开发语言·设计模式·golang
小糖学代码20 小时前
Linux:11.线程概念与控制
linux·服务器·c语言·开发语言·c++