装饰器模式(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流添加加密、压缩等功能。