装饰器模式(Decorator Pattern) 是一种结构型设计模式,它允许你动态地给一个对象添加额外的功能或行为,而无需修改其原始类。它通过将对象包装在“装饰器”类中来实现功能的扩展,比继承更灵活。
核心思想
- 动态扩展功能,在运行时添加或移除功能,比静态继承更灵活。
- 避免类爆炸,如果用继承实现多种组合,类数量会指数级增长;装饰器可以组合使用。
- 符合开闭原则,对扩展开放(加装饰器),对修改关闭(不改原类)。
- 职责分离,每个装饰器只负责一项功能,代码更清晰。
缺点
- 增加了系统的复杂性(更多小类)。
- 调试时堆栈可能变深。
- 客户端可能需要创建复杂的装饰链。
代码示例
示例:咖啡店系统
基础咖啡(Espresso)价格 20 元;
添加牛奶(Milk)+5 元;
添加糖(Sugar)+3 元;
添加牛奶(Milk)+5 元 + 添加糖(Sugar)+3 元;
使用装饰器动态计算价格。
#include <iostream>
#include <string>
#include <memory>
// 使用别名简化代码
using std::string;
using std::unique_ptr;
// ==================== 组件接口 ====================
class Coffee {
public:
virtual ~Coffee() = default;
virtual double cost() const = 0;
virtual string description() const = 0;
};
// ==================== 具体组件:基础咖啡 ====================
class Espresso : public Coffee {
public:
double cost() const override {
return 20.0;
}
string description() const override {
return "浓缩咖啡";
}
};
// ==================== 装饰器基类 ====================
class CoffeeDecorator : public Coffee {
protected:
unique_ptr<Coffee> coffee; // 使用智能指针持有被装饰对象
public:
// 通过移动语义接收 unique_ptr
CoffeeDecorator(unique_ptr<Coffee> c) : coffee(std::move(c)) {}
// 默认析构即可,unique_ptr 自动清理
virtual ~CoffeeDecorator() = default;
double cost() const override {
return coffee->cost();
}
string description() const override {
return coffee->description();
}
};
// ==================== 具体装饰器1:加牛奶 ====================
class Milk : public CoffeeDecorator {
public:
explicit Milk(unique_ptr<Coffee> c) : CoffeeDecorator(std::move(c)) {}
double cost() const override {
return coffee->cost() + 5.0; // 原价 +5
}
string description() const override {
return coffee->description() + " + 牛奶";
}
};
// ==================== 具体装饰器2:加糖 ====================
class Sugar : public CoffeeDecorator {
public:
explicit Sugar(unique_ptr<Coffee> c) : CoffeeDecorator(std::move(c)) {}
double cost() const override {
return coffee->cost() + 3.0; // 原价 +3
}
string description() const override {
return coffee->description() + " + 糖";
}
};
// ==================== 测试 ====================
int main() {
// 1. 一杯基础咖啡
auto c1 = std::make_unique<Espresso>();
std::cout << c1->description() << " 价格:" << c1->cost() << "元\n\n";
// 2. 咖啡 + 牛奶
auto c2 = std::make_unique<Milk>(std::make_unique<Espresso>());
std::cout << c2->description() << " 价格:" << c2->cost() << "元\n\n";
// 3. 咖啡 + 牛奶 + 糖
auto c3 = std::make_unique<Sugar>(
std::make_unique<Milk>(
std::make_unique<Espresso>()
)
);
std::cout << c3->description() << " 价格:" << c3->cost() << "元\n";
// 不需要手动 delete!析构时自动释放
return 0;
}
进阶-使用模板
// ==================== 模板装饰器基类 ====================
// 所有装饰器继承自这个模板
template<typename T>
class CoffeeDecorator : public Coffee, public T {
public:
// 继承被装饰对象,并转发所有接口
explicit CoffeeDecorator(unique_ptr<T> coffee)
: coffee(std::move(coffee)) {}
protected:
unique_ptr<T> coffee; // 持有被装饰的对象
};
// ==================== 具体装饰器1:加牛奶 ====================
class Milk : public CoffeeDecorator<Coffee> {
public:
using CoffeeDecorator::CoffeeDecorator; // 继承构造函数
double cost() const override {
return coffee->cost() + 5.0;
}
string description() const override {
return coffee->description() + " + 牛奶";
}
};
// ==================== 具体装饰器2:加糖 ====================
class Sugar : public CoffeeDecorator<Coffee> {
public:
using CoffeeDecorator::CoffeeDecorator;
double cost() const override {
return coffee->cost() + 3.0;
}
string description() const override {
return coffee->description() + " + 糖";
}
};
// ==================== 具体装饰器3:加奶油 ====================
class Whip : public CoffeeDecorator<Coffee> {
public:
using CoffeeDecorator::CoffeeDecorator;
double cost() const override {
return coffee->cost() + 4.0;
}
string description() const override {
return coffee->description() + " + 奶油";
}
};