装饰者模式(Decorator Pattern)是一种结构型设计模式,它允许动态地向一个对象添加额外的职责,同时又不改变其结构。这种模式通过创建装饰器类来包装原有类,提供了比继承更有弹性的替代方案。
核心角色
组件接口(Component): 定义对象接口,可以动态添加职责
具体组件(ConcreteComponent): 实现组件接口的基本对象
装饰器抽象类(Decorator): 持有组件引用并实现组件接口
具体装饰器(ConcreteDecorator): 向组件添加具体职责
使用场景
装饰者模式在以下情况下特别适用:
需要在不影响其他对象的情况下动态添加职责
需要撤销或动态修改对象的功能
通过继承扩展不切实际(如子类爆炸)
需要为对象添加大量可选功能
典型应用案例
GUI组件装饰(如添加滚动条、边框)
I/O流处理(Java的BufferedInputStream等)
日志记录增强(添加时间戳、调用链信息)
权限校验装饰(在核心逻辑外添加权限层)
游戏角色装备系统(动态添加武器/防具效果)
C++代码实现示例
示例1:文本格式化装饰器
#include <iostream>
#include <string>
#include <memory>
// 组件接口
class Text {
public:
virtual ~Text() = default;
virtual std::string render() const = 0;
};
// 具体组件
class PlainText : public Text {
std::string content;
public:
explicit PlainText(const std::string& str) : content(str) {}
std::string render() const override { return content; }
};
// 装饰器基类
class TextDecorator : public Text {
protected:
std::unique_ptr<Text> text;
public:
explicit TextDecorator(std::unique_ptr<Text> t) : text(std::move(t)) {}
std::string render() const override { return text->render(); }
};
// 具体装饰器 - 加粗
class BoldDecorator : public TextDecorator {
public:
using TextDecorator::TextDecorator;
std::string render() const override {
return "<b>" + text->render() + "</b>";
}
};
// 具体装饰器 - 斜体
class ItalicDecorator : public TextDecorator {
public:
using TextDecorator::TextDecorator;
std::string render() const override {
return "<i>" + text->render() + "</i>";
}
};
// 具体装饰器 - 下划线
class UnderlineDecorator : public TextDecorator {
public:
using TextDecorator::TextDecorator;
std::string render() const override {
return "<u>" + text->render() + "</u>";
}
};
// 客户端代码
int main() {
auto text = std::make_unique<PlainText>("Hello, World!");
// 动态添加装饰
auto decoratedText = std::make_unique<BoldDecorator>(
std::make_unique<ItalicDecorator>(
std::make_unique<UnderlineDecorator>(std::move(text))
)
);
std::cout << decoratedText->render() << std::endl;
// 输出: <b><i><u>Hello, World!</u></i></b>
return 0;
}
示例2:咖啡订单系统
#include <iostream>
#include <string>
#include <memory>
// 组件接口 - 饮料
class Beverage {
public:
virtual ~Beverage() = default;
virtual std::string getDescription() const = 0;
virtual double cost() const = 0;
};
// 具体组件 - 浓缩咖啡
class Espresso : public Beverage {
public:
std::string getDescription() const override {
return "Espresso";
}
double cost() const override { return 1.99; }
};
// 具体组件 - 黑咖啡
class HouseBlend : public Beverage {
public:
std::string getDescription() const override {
return "House Blend Coffee";
}
double cost() const override { return 0.89; }
};
// 装饰器基类 - 调料
class CondimentDecorator : public Beverage {
protected:
std::unique_ptr<Beverage> beverage;
public:
explicit CondimentDecorator(std::unique_ptr<Beverage> b)
: beverage(std::move(b)) {}
std::string getDescription() const override = 0;
};
// 具体装饰器 - 摩卡
class Mocha : public CondimentDecorator {
public:
using CondimentDecorator::CondimentDecorator;
std::string getDescription() const override {
return beverage->getDescription() + ", Mocha";
}
double cost() const override {
return beverage->cost() + 0.20;
}
};
// 具体装饰器 - 奶泡
class Whip : public CondimentDecorator {
public:
using CondimentDecorator::CondimentDecorator;
std::string getDescription() const override {
return beverage->getDescription() + ", Whip";
}
double cost() const override {
return beverage->cost() + 0.10;
}
};
// 具体装饰器 - 大豆
class Soy : public CondimentDecorator {
public:
using CondimentDecorator::CondimentDecorator;
std::string getDescription() const override {
return beverage->getDescription() + ", Soy";
}
double cost() const override {
return beverage->cost() + 0.15;
}
};
// 客户端代码
int main() {
// 点一杯双倍摩卡加奶泡的浓缩咖啡
auto beverage = std::make_unique<Espresso>();
beverage = std::make_unique<Mocha>(std::move(beverage));
beverage = std::make_unique<Mocha>(std::move(beverage));
beverage = std::make_unique<Whip>(std::move(beverage));
std::cout << beverage->getDescription()
<< " $" << beverage->cost() << std::endl;
// 输出: Espresso, Mocha, Mocha, Whip $2.49
// 点一杯加大豆和奶泡的黑咖啡
auto beverage2 = std::make_unique<HouseBlend>();
beverage2 = std::make_unique<Soy>(std::move(beverage2));
beverage2 = std::make_unique<Whip>(std::move(beverage2));
std::cout << beverage2->getDescription()
<< " $" << beverage2->cost() << std::endl;
// 输出: House Blend Coffee, Soy, Whip $1.14
return 0;
}
装饰者模式的优缺点
优点
比继承更灵活:可以动态添加/删除功能
避免类爆炸:不需要为每种组合创建子类
符合开闭原则:可以扩展功能而不修改原有代码
职责单一:每个装饰类只关注特定功能
运行时配置:可以在运行时决定如何装饰对象
缺点
增加复杂性:会引入大量小类,可能使系统更难理解
多层装饰问题:过度使用会导致对象被多层包装,调试困难
初始化复杂:创建高度装饰的对象需要多步构造
与相关模式对比
模式 区别
适配器模式 改变接口,装饰者模式保持接口
组合模式 装饰者模式只有一个子组件
策略模式 改变对象核心行为,装饰者模式添加辅助功能
代理模式 控制访问,装饰者模式增强功能
装饰者模式是扩展对象功能的强大工具,特别适合需要动态、透明地添加职责的场景。通过合理使用,可以构建出高度灵活且易于维护的系统。
1016

被折叠的 条评论
为什么被折叠?



