装饰器模式的核心思想是通过组合替代继承,在不改变原有对象结构的基础上,动态给对象添加额外功能。传统的装饰器模式实现中,功能添加需要逐层嵌套对象,移除功能也需要手动处理嵌套关系,操作不够灵活。而基于链式调用的实现方式,可以让功能添加和移除像链式操作一样简单,大幅提升使用的便捷性。

传统装饰器模式的局限性
传统装饰器模式通常会定义一个抽象组件接口,具体组件和装饰器都实现该接口,装饰器内部持有抽象组件的指针,通过重写接口方法实现功能扩展。这种方式虽然满足开闭原则,但添加多个功能时需要层层包装对象,代码可读性较差,且移除某个功能时需要重新调整包装结构,操作成本高。
链式调用装饰器的设计思路
要实现支持动态添加移除功能的链式调用装饰器,核心设计点有三个:
- 抽象组件接口定义基础功能方法,同时定义添加、移除装饰器的接口
- 装饰器基类实现添加、移除方法,返回当前对象的引用支持链式调用
- 每个具体装饰器实现自身扩展功能,同时维护装饰器链的管理逻辑
完整实现代码示例
以下是一个支持动态添加移除功能的链式调用装饰器实现,以文本处理组件为例,扩展文本加粗、斜体、下划线功能:
#include <iostream>
#include <string>
#include <vector>
#include <memory>
// 抽象组件接口
class TextComponent {
public:
virtual ~TextComponent() = default;
virtual std::string render() const = 0;
// 添加装饰器,返回当前对象引用支持链式调用
virtual TextComponent& addDecorator(std::shared_ptr<TextComponent> decorator) = 0;
// 移除指定类型的装饰器,返回当前对象引用支持链式调用
virtual TextComponent& removeDecorator(const std::string& decoratorType) = 0;
};
// 具体基础组件:普通文本
class PlainText : public TextComponent {
private:
std::string content;
std::vector<std::shared_ptr<TextComponent>> decorators;
public:
explicit PlainText(const std::string& text) : content(text) {}
std::string render() const override {
std::string result = content;
// 依次执行所有装饰器的处理
for (auto it = decorators.begin(); it != decorators.end(); ++it) {
result = (*it)->render();
}
return result;
}
TextComponent& addDecorator(std::shared_ptr<TextComponent> decorator) override {
decorators.push_back(decorator);
return *this;
}
TextComponent& removeDecorator(const std::string& decoratorType) override {
for (auto it = decorators.begin(); it != decorators.end(); ) {
// 判断装饰器类型是否匹配,这里通过typeid简单判断,实际可自定义类型标识
if (typeid(*it.get()).name() == decoratorType) {
it = decorators.erase(it);
} else {
++it;
}
}
return *this;
}
};
// 抽象装饰器基类
class TextDecorator : public TextComponent {
protected:
std::shared_ptr<TextComponent> component;
public:
explicit TextDecorator(std::shared_ptr<TextComponent> comp) : component(comp) {}
std::string render() const override {
return component->render();
}
TextComponent& addDecorator(std::shared_ptr<TextComponent> decorator) override {
component->addDecorator(decorator);
return *this;
}
TextComponent& removeDecorator(const std::string& decoratorType) override {
component->removeDecorator(decoratorType);
return *this;
}
};
// 具体装饰器:加粗
class BoldDecorator : public TextDecorator {
public:
explicit BoldDecorator(std::shared_ptr<TextComponent> comp) : TextDecorator(comp) {}
std::string render() const override {
return "<b>" + component->render() + "</b>";
}
};
// 具体装饰器:斜体
class ItalicDecorator : public TextDecorator {
public:
explicit ItalicDecorator(std::shared_ptr<TextComponent> comp) : TextDecorator(comp) {}
std::string render() const override {
return "<i>" + component->render() + "</i>";
}
};
// 具体装饰器:下划线
class UnderlineDecorator : public TextDecorator {
public:
explicit UnderlineDecorator(std::shared_ptr<TextComponent> comp) : TextDecorator(comp) {}
std::string render() const override {
return "<u>" + component->render() + "</u>";
}
};
int main() {
// 创建基础文本对象
auto text = std::make_shared<PlainText>("Hello World");
// 链式添加装饰器
text->addDecorator(std::make_shared<BoldDecorator>(text))
->addDecorator(std::make_shared<ItalicDecorator>(text))
->addDecorator(std::make_shared<UnderlineDecorator>(text));
std::cout << "添加所有装饰器后:" << text->render() << std::endl;
// 链式移除斜体装饰器
text->removeDecorator(typeid(ItalicDecorator).name());
std::cout << "移除斜体装饰器后:" << text->render() << std::endl;
return 0;
}
实现要点说明
上述代码中,PlainText作为基础组件,维护了一个装饰器列表,所有的装饰器操作都委托给基础组件管理。每个装饰器都继承自TextDecorator,重写render方法实现功能扩展。添加和移除方法都返回当前对象引用,因此可以支持链式调用。
需要注意的是,示例中使用typeid判断装饰器类型仅为演示,实际项目中可以自定义装饰器的类型标识字段,避免typeid带来的兼容性问题。另外,装饰器的生命周期通过智能指针管理,避免手动内存释放的问题。
使用场景与优势
这种基于链式调用的装饰器模式适合需要频繁动态扩展、调整对象功能的场景,比如UI组件样式动态修改、请求处理流程动态拼接、日志输出格式动态配置等。相比传统实现,它的优势在于调用流程更清晰,功能调整更灵活,不需要修改原有对象代码即可完成功能的新增和移除。