1. 模式定义
装饰模式(Decorator Pattern)是一种结构型设计模式 ,允许动态地 向一个现有对象添加新的功能,同时不改变其结构。这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供额外的功能。
2. 核心特点
- 替代继承:提供比继承更灵活的扩展方式
- 透明性:装饰类与被装饰类具有相同的接口
- 动态性:运行时动态添加/撤销功能
- 开闭原则:对扩展开放,对修改关闭
3. 模式结构
<<interface>>
Component
+operation() : string
ConcreteComponent
+operation() : string
Decorator
-component: Component
+Decorator(Component* comp)
+operation() : string
ConcreteDecoratorA
-addedState: string
+operation() : string
+addedBehavior() : string
ConcreteDecoratorB
+operation() : string
+addedBehavior() : string
4. 应用场景
典型场景:
- IO流处理(Java/C++流库)
- GUI组件(添加滚动条、边框等)
- 咖啡/披萨订单系统(添加配料)
- 权限系统(动态添加角色权限)
- 日志系统(不同格式/输出方式)
- 数据压缩/加密(透明附加功能)
实战案例:
- 游戏装备系统(武器附魔)
- 文本编辑器(字体、颜色、下划线等格式)
- 图片处理(滤镜、水印、边框)
5. C++代码示例
基础示例:咖啡订单系统
cpp
#include <iostream>
#include <memory>
#include <string>
// 抽象组件:饮料
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 "浓缩咖啡";
}
double cost() const override {
return 25.0;
}
};
// 具体组件:混合咖啡
class HouseBlend : public Beverage {
public:
std::string getDescription() const override {
return "混合咖啡";
}
double cost() const override {
return 20.0;
}
};
// 抽象装饰类
class CondimentDecorator : public Beverage {
protected:
std::unique_ptr<Beverage> beverage;
public:
CondimentDecorator(std::unique_ptr<Beverage> bev)
: beverage(std::move(bev)) {}
virtual ~CondimentDecorator() = default;
std::string getDescription() const override {
return beverage->getDescription();
}
double cost() const override {
return beverage->cost();
}
};
// 具体装饰:牛奶
class Milk : public CondimentDecorator {
public:
Milk(std::unique_ptr<Beverage> bev)
: CondimentDecorator(std::move(bev)) {}
std::string getDescription() const override {
return beverage->getDescription() + " + 牛奶";
}
double cost() const override {
return beverage->cost() + 5.0;
}
};
// 具体装饰:摩卡
class Mocha : public CondimentDecorator {
public:
Mocha(std::unique_ptr<Beverage> bev)
: CondimentDecorator(std::move(bev)) {}
std::string getDescription() const override {
return beverage->getDescription() + " + 摩卡";
}
double cost() const override {
return beverage->cost() + 8.0;
}
};
// 具体装饰:奶泡
class Whip : public CondimentDecorator {
public:
Whip(std::unique_ptr<Beverage> bev)
: CondimentDecorator(std::move(bev)) {}
std::string getDescription() const override {
return beverage->getDescription() + " + 奶泡";
}
double cost() const override {
return beverage->cost() + 4.0;
}
};
// 客户端使用
int main() {
// 一杯浓缩咖啡 + 双份牛奶
auto beverage1 = std::make_unique<Espresso>();
beverage1 = std::make_unique<Milk>(std::move(beverage1));
beverage1 = std::make_unique<Milk>(std::move(beverage1));
std::cout << "订单1: " << beverage1->getDescription()
<< " | 价格: ¥" << beverage1->cost() << std::endl;
// 混合咖啡 + 摩卡 + 奶泡
auto beverage2 = std::make_unique<HouseBlend>();
beverage2 = std::make_unique<Mocha>(std::move(beverage2));
beverage2 = std::make_unique<Whip>(std::move(beverage2));
std::cout << "订单2: " << beverage2->getDescription()
<< " | 价格: ¥" << beverage2->cost() << std::endl;
return 0;
}
高级示例:数据流处理
cpp
#include <iostream>
#include <string>
#include <algorithm>
// 抽象数据流
class DataStream {
public:
virtual ~DataStream() = default;
virtual std::string read() = 0;
virtual void write(const std::string& data) = 0;
};
// 具体组件:文件流
class FileStream : public DataStream {
public:
std::string read() override {
return "原始文件数据";
}
void write(const std::string& data) override {
std::cout << "写入文件: " << data << std::endl;
}
};
// 抽象装饰器
class StreamDecorator : public DataStream {
protected:
DataStream* stream;
public:
StreamDecorator(DataStream* s) : stream(s) {}
virtual ~StreamDecorator() { delete stream; }
std::string read() override {
return stream->read();
}
void write(const std::string& data) override {
stream->write(data);
}
};
// 加密装饰器
class EncryptionDecorator : public StreamDecorator {
private:
std::string encrypt(const std::string& data) {
std::string encrypted = data;
for (char& c : encrypted) {
c = c ^ 0xFF; // 简单的异或加密
}
return encrypted;
}
std::string decrypt(const std::string& data) {
return encrypt(data); // 异或两次恢复原值
}
public:
EncryptionDecorator(DataStream* s) : StreamDecorator(s) {}
std::string read() override {
std::string data = StreamDecorator::read();
return decrypt(data);
}
void write(const std::string& data) override {
std::string encrypted = encrypt(data);
StreamDecorator::write(encrypted);
}
};
// 压缩装饰器
class CompressionDecorator : public StreamDecorator {
private:
std::string compress(const std::string& data) {
// 模拟压缩:重复字符计数
std::string compressed;
for (size_t i = 0; i < data.length(); ++i) {
if (i == 0 || data[i] != data[i-1]) {
compressed += data[i];
}
}
return compressed;
}
std::string decompress(const std::string& data) {
// 模拟解压(简单场景)
return data;
}
public:
CompressionDecorator(DataStream* s) : StreamDecorator(s) {}
std::string read() override {
std::string data = StreamDecorator::read();
return decompress(data);
}
void write(const std::string& data) override {
std::string compressed = compress(data);
StreamDecorator::write(compressed);
}
};
// 使用示例
int main() {
// 基础文件流
DataStream* file = new FileStream();
file->write("Hello World");
// 添加加密功能
DataStream* encrypted = new EncryptionDecorator(file);
encrypted->write("Sensitive Data");
// 添加压缩+加密功能
DataStream* compressed = new CompressionDecorator(
new EncryptionDecorator(new FileStream())
);
compressed->write("Important Content");
delete compressed;
delete encrypted;
return 0;
}
6. 装饰模式 vs 继承
装饰模式
核心组件
装饰器1
装饰器2
装饰器3
继承方式
父类
子类1
子类2
子类3
孙类1-1
孙类1-2
7. 优点与缺点
优点 ✅
- 灵活性:运行时动态添加/删除功能
- 避免类爆炸:无需为每个组合创建子类
- 单一职责:每个装饰类只负责一个功能
- 组合优于继承:更符合设计原则
缺点 ❌
- 增加复杂度:产生大量小类
- 调试困难:层层包装,追踪较难
- 类型识别问题:装饰后的对象类型发生变化
8. 最佳实践
- 保持接口一致:装饰类必须实现被装饰类的接口
- 避免过度装饰:装饰链不要超过3-4层
- 考虑使用工厂模式:创建复杂的装饰组合
- 注意性能影响:每层装饰都有额外开销
9.装饰模式与工厂模式的结合
装饰模式和工厂模式的结合是一种常见的设计模式组合,可以有效解决装饰对象的创建和管理问题。
9.1 为什么要结合?
客户端
直接创建装饰对象
问题1: 创建逻辑分散
问题2: 容易出错
问题3: 难以统一管理
工厂模式
解决方案
集中创建逻辑
保证正确性
简化客户端代码
9.2 结合方式
方式一:简单工厂 + 装饰模式
cpp
#include <iostream>
#include <memory>
#include <string>
#include <map>
// 饮料基类
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 "浓缩咖啡"; }
double cost() const override { return 25.0; }
};
class Latte : public Beverage {
public:
std::string getDescription() const override { return "拿铁咖啡"; }
double cost() const override { return 30.0; }
};
// 装饰器基类
class CondimentDecorator : public Beverage {
protected:
std::unique_ptr<Beverage> beverage;
public:
CondimentDecorator(std::unique_ptr<Beverage> bev)
: beverage(std::move(bev)) {}
};
// 具体装饰器
class Milk : public CondimentDecorator {
public:
Milk(std::unique_ptr<Beverage> bev) : CondimentDecorator(std::move(bev)) {}
std::string getDescription() const override {
return beverage->getDescription() + " + 牛奶";
}
double cost() const override { return beverage->cost() + 5.0; }
};
class Mocha : public CondimentDecorator {
public:
Mocha(std::unique_ptr<Beverage> bev) : CondimentDecorator(std::move(bev)) {}
std::string getDescription() const override {
return beverage->getDescription() + " + 摩卡";
}
double cost() const override { return beverage->cost() + 8.0; }
};
// ========== 简单工厂 ==========
class CoffeeFactory {
public:
enum CoffeeType { ESPRESSO, LATTE };
static std::unique_ptr<Beverage> createCoffee(CoffeeType type) {
switch (type) {
case ESPRESSO: return std::make_unique<Espresso>();
case LATTE: return std::make_unique<Latte>();
default: return nullptr;
}
}
// 预定义的组合
static std::unique_ptr<Beverage> createSignatureLatte() {
auto coffee = std::make_unique<Latte>();
coffee = std::make_unique<Milk>(std::move(coffee));
coffee = std::make_unique<Mocha>(std::move(coffee));
return coffee;
}
};
// 使用示例
int main() {
// 使用工厂创建基础咖啡
auto coffee1 = CoffeeFactory::createCoffee(CoffeeFactory::ESPRESSO);
coffee1 = std::make_unique<Milk>(std::move(coffee1));
std::cout << coffee1->getDescription() << ": ¥" << coffee1->cost() << std::endl;
// 使用工厂创建复杂组合
auto signature = CoffeeFactory::createSignatureLatte();
std::cout << signature->getDescription() << ": ¥" << signature->cost() << std::endl;
return 0;
}
方式二:工厂方法 + 装饰模式
cpp
#include <iostream>
#include <memory>
#include <vector>
// 装饰器类型枚举
enum class Topping { MILK, MOCHA, WHIP, SOY };
// 抽象工厂
class BeverageFactory {
public:
virtual ~BeverageFactory() = default;
virtual std::unique_ptr<Beverage> createBeverage() = 0;
virtual std::unique_ptr<Beverage> createWithToppings(
const std::vector<Topping>& toppings) = 0;
};
// 具体工厂:浓缩咖啡工厂
class EspressoFactory : public BeverageFactory {
private:
std::unique_ptr<Beverage> applyToppings(
std::unique_ptr<Beverage> beverage,
const std::vector<Topping>& toppings) {
for (auto topping : toppings) {
switch (topping) {
case Topping::MILK:
beverage = std::make_unique<Milk>(std::move(beverage));
break;
case Topping::MOCHA:
beverage = std::make_unique<Mocha>(std::move(beverage));
break;
default:
break;
}
}
return beverage;
}
public:
std::unique_ptr<Beverage> createBeverage() override {
return std::make_unique<Espresso>();
}
std::unique_ptr<Beverage> createWithToppings(
const std::vector<Topping>& toppings) override {
auto beverage = createBeverage();
return applyToppings(std::move(beverage), toppings);
}
};
// 使用示例
int main() {
EspressoFactory factory;
// 创建纯浓缩咖啡
auto espresso = factory.createBeverage();
// 创建加牛奶和摩卡的浓缩咖啡
auto deluxe = factory.createWithToppings({Topping::MILK, Topping::MOCHA});
std::cout << deluxe->getDescription() << ": ¥" << deluxe->cost() << std::endl;
return 0;
}
方式三:抽象工厂 + 装饰模式
cpp
#include <iostream>
#include <memory>
#include <map>
#include <functional>
// 装饰器创建函数类型
using DecoratorCreator = std::function<std::unique_ptr<Beverage>(std::unique_ptr<Beverage>)>;
// 装饰器注册表
class DecoratorRegistry {
private:
std::map<std::string, DecoratorCreator> creators;
public:
void registerDecorator(const std::string& name, DecoratorCreator creator) {
creators[name] = creator;
}
DecoratorCreator getCreator(const std::string& name) {
auto it = creators.find(name);
if (it != creators.end()) {
return it->second;
}
return nullptr;
}
};
// 全局注册表
DecoratorRegistry& getRegistry() {
static DecoratorRegistry registry;
return registry;
}
// 自动注册类
class AutoRegister {
public:
AutoRegister(const std::string& name, DecoratorCreator creator) {
getRegistry().registerDecorator(name, creator);
}
};
// 注册装饰器(使用静态初始化)
static AutoRegister registerMilk("milk", [](std::unique_ptr<Beverage> b) {
return std::make_unique<Milk>(std::move(b));
});
static AutoRegister registerMocha("mocha", [](std::unique_ptr<Beverage> b) {
return std::make_unique<Mocha>(std::move(b));
});
// 抽象工厂:支持配置驱动
class ConfigurableCoffeeFactory {
private:
std::string baseCoffee;
std::vector<std::string> toppings;
public:
ConfigurableCoffeeFactory(const std::string& coffee,
const std::vector<std::string>& toppings)
: baseCoffee(coffee), toppings(toppings) {}
std::unique_ptr<Beverage> create() {
std::unique_ptr<Beverage> beverage;
// 创建基础咖啡
if (baseCoffee == "espresso") {
beverage = std::make_unique<Espresso>();
} else if (baseCoffee == "latte") {
beverage = std::make_unique<Latte>();
} else {
return nullptr;
}
// 动态应用装饰器
for (const auto& topping : toppings) {
auto creator = getRegistry().getCreator(topping);
if (creator) {
beverage = creator(std::move(beverage));
}
}
return beverage;
}
};
// 使用示例:类似配置文件解析
int main() {
// 模拟从配置文件读取
std::map<std::string, std::vector<std::string>> orders = {
{"order1", {"espresso", "milk", "mocha"}},
{"order2", {"latte", "milk"}},
{"order3", {"espresso", "milk", "milk", "mocha"}} // 双份牛奶
};
for (const auto& [orderId, config] : orders) {
if (config.size() < 1) continue;
std::string coffeeType = config[0];
std::vector<std::string> toppings(config.begin() + 1, config.end());
ConfigurableCoffeeFactory factory(coffeeType, toppings);
auto beverage = factory.create();
if (beverage) {
std::cout << orderId << ": " << beverage->getDescription()
<< " | ¥" << beverage->cost() << std::endl;
}
}
return 0;
}
方式四:建造者模式结合
cpp
#include <iostream>
#include <memory>
#include <vector>
// 装饰器构建器
class CoffeeBuilder {
private:
std::unique_ptr<Beverage> beverage;
public:
CoffeeBuilder& setBase(std::unique_ptr<Beverage> base) {
beverage = std::move(base);
return *this;
}
CoffeeBuilder& addMilk() {
if (beverage) {
beverage = std::make_unique<Milk>(std::move(beverage));
}
return *this;
}
CoffeeBuilder& addMocha() {
if (beverage) {
beverage = std::make_unique<Mocha>(std::move(beverage));
}
return *this;
}
CoffeeBuilder& addWhip() {
if (beverage) {
beverage = std::make_unique<Whip>(std::move(beverage));
}
return *this;
}
std::unique_ptr<Beverage> build() {
return std::move(beverage);
}
};
// 工厂类使用建造者
class CoffeeShop {
public:
static std::unique_ptr<Beverage> createStandardLatte() {
return CoffeeBuilder()
.setBase(std::make_unique<Latte>())
.addMilk()
.build();
}
static std::unique_ptr<Beverage> createDeluxeMocha() {
return CoffeeBuilder()
.setBase(std::make_unique<Espresso>())
.addMilk()
.addMocha()
.addWhip()
.build();
}
// 支持自定义
static std::unique_ptr<Beverage> customOrder(
std::unique_ptr<Beverage> base,
bool hasMilk, bool hasMocha, bool hasWhip) {
CoffeeBuilder builder;
builder.setBase(std::move(base));
if (hasMilk) builder.addMilk();
if (hasMocha) builder.addMocha();
if (hasWhip) builder.addWhip();
return builder.build();
}
};
int main() {
auto latte = CoffeeShop::createStandardLatte();
std::cout << latte->getDescription() << ": ¥" << latte->cost() << std::endl;
auto mocha = CoffeeShop::createDeluxeMocha();
std::cout << mocha->getDescription() << ": ¥" << mocha->cost() << std::endl;
auto custom = CoffeeShop::customOrder(
std::make_unique<Latte>(),
true, true, false // 加牛奶和摩卡,不加奶泡
);
std::cout << custom->getDescription() << ": ¥" << custom->cost() << std::endl;
return 0;
}
3. 结合的优势对比
使用工厂
客户端
Factory.create
自动应用装饰器
返回完整对象
不使用工厂
客户端
new Espresso
new Milk
new Mocha
...
4. 最佳实践建议
| 场景 | 推荐方式 | 原因 |
|---|---|---|
| 装饰器种类少(<5种) | 简单工厂 | 实现简单,够用 |
| 装饰器有层次关系 | 工厂方法 | 支持继承扩展 |
| 需要灵活配置 | 抽象工厂+注册表 | 配置驱动,热插拔 |
| 复杂构建过程 | 建造者模式 | 链式调用,可读性强 |
5. 实际应用场景
cpp
// 实战:UI组件装饰工厂
class UIComponentFactory {
public:
static std::unique_ptr<Component> createStyledButton(
const std::string& text,
const std::vector<std::string>& styles) {
auto button = std::make_unique<Button>(text);
for (const auto& style : styles) {
if (style == "border") {
button = std::make_unique<BorderDecorator>(std::move(button));
} else if (style == "shadow") {
button = std::make_unique<ShadowDecorator>(std::move(button));
} else if (style == "rounded") {
button = std::make_unique<RoundedDecorator>(std::move(button));
}
}
return button;
}
};
// 使用
auto btn = UIComponentFactory::createStyledButton("Click Me",
{"border", "shadow", "rounded"});
这种结合方式既保持了装饰模式的灵活性,又通过工厂模式解决了对象创建的复杂度问题,是实际项目中的常用组合。