当前位置: 首页 > news >正文

C++设计模式(GOF-23)——04 C++装饰器模式(Decorator)(一个类同时继承和组合另一个类)解决类爆炸问题、模板装饰器

文章目录

  • 1. 装饰器模式的核心思想
  • 2. 装饰器模式的结构
    • 关键点:
    • 类图关系说明
  • 3. 装饰器模式的适用场景
    • 示例:流操作功能扩展
    • 动态组合调用流程
    • 调用流程图示
  • 4. 装饰器模式与组合模式的区别
  • 5. 总结
    • 装饰器模式关键点
    • 代码优化建议

在 C++ 中,当一个类 同时继承和组合另一个类时,这种设计模式通常被称为 装饰器模式(Decorator Pattern)。以下是详细解释:


1. 装饰器模式的核心思想

装饰器模式是一种结构型设计模式,其核心目的是通过组合和继承的方式,动态地为对象添加职责,而不通过继承硬编码的方式来扩展功能。

  • 继承:装饰器类(Decorator)继承自目标类(Component)的接口或抽象类。
  • 组合:装饰器类内部组合一个目标类的对象(通常是通过构造函数传入),从而在运行时动态地扩展功能。

这种设计模式允许你在不修改原有类代码的情况下,通过组合的方式灵活地扩展功能,同时避免了继承可能导致的类爆炸问题。


2. 装饰器模式的结构

装饰器模式的典型结构如下:

// 抽象组件接口,定义核心操作
class Component {
public:virtual void Operation() = 0;  // 纯虚函数,强制子类实现virtual ~Component() {}        // 虚析构函数确保安全释放资源
};// 具体组件类,实现核心功能
class ConcreteComponent : public Component {
public:void Operation() override {std::cout << "ConcreteComponent Operation" << std::endl;}
};// 抽象装饰器类,继承自组件接口并组合组件对象
class Decorator : public Component {
protected:Component* component_;  // 持有组件对象指针
public:// 通过构造函数注入组件对象Decorator(Component* component) : component_(component) {}void Operation() override {component_->Operation();  // 默认调用被装饰对象的操作}
};// 具体装饰器A,扩展新功能
class ConcreteDecoratorA : public Decorator {
private:std::string addedState_;  // 新增状态字段
public:// 通过构造函数注入组件对象ConcreteDecoratorA(Component* component) : Decorator(component) {}void Operation() override {// 调用父类(装饰器基类)的OperationDecorator::Operation();// 添加新功能std::cout << "ConcreteDecoratorA added functionality" << std::endl;}
};// 具体装饰器B,扩展新功能
class ConcreteDecoratorB : public Decorator {
private:std::string addedBehavior_;  // 新增行为字段
public:ConcreteDecoratorB(Component* component) : Decorator(component) {}void Operation() override {// 调用父类(装饰器基类)的OperationDecorator::Operation();// 添加新功能std::cout << "ConcreteDecoratorB added functionality" << std::endl;}
};

关键点:

  • 继承Decorator 类继承自 Component,从而能够替代 Component 的使用。
  • 组合Decorator 类内部组合一个 Component 对象(通过构造函数传入),并在其方法中调用该对象的方法。
  • 动态扩展:通过嵌套多个装饰器(如 ConcreteDecoratorAConcreteDecoratorB),可以在运行时动态地添加功能。

类图关系说明

1
1
«interface»
Component
+virtual void Operation()
ConcreteComponent
+void Operation()
Decorator
+Component* component_
+Decorator(Component*)
+void Operation()
ConcreteDecoratorA
+std::string addedState_
+ConcreteDecoratorA(Component*)
+void Operation()
ConcreteDecoratorB
+std::string addedBehavior_
+ConcreteDecoratorB(Component*)
+void Operation()

3. 装饰器模式的适用场景

  • 需要动态、透明地给对象添加职责,而不是通过继承硬编码。
  • 扩展功能时,不希望使用静态继承导致的类爆炸
  • 需要为对象添加多个可选的功能,并且这些功能可以独立组合。

示例:流操作功能扩展

假设有一个 Stream 接口,需要为不同的流(如文件流、网络流)添加压缩、加密等功能:

// 流接口定义
class Stream {
public:virtual void Write(const std::string& data) = 0;  // 核心操作virtual ~Stream() {}                            // 虚析构函数
};// 具体文件流实现
class FileStream : public Stream {
public:void Write(const std::string& data) override {std::cout << "Writing to file: " << data << std::endl;}
};// 压缩装饰器,组合流对象
class CompressedStream : public Stream {
private:Stream* stream_;  // 持有流对象指针
public:// 通过构造函数注入流对象CompressedStream(Stream* stream) : stream_(stream) {}void Write(const std::string& data) override {// 数据压缩逻辑std::string compressedData = "Compressed(" + data + ")";// 调用被装饰对象的Write方法stream_->Write(compressedData);}
};// 加密装饰器,组合流对象
class EncryptedStream : public Stream {
private:Stream* stream_;  // 持有流对象指针
public:// 通过构造函数注入流对象EncryptedStream(Stream* stream) : stream_(stream) {}void Write(const std::string& data) override {// 数据加密逻辑std::string encryptedData = "Encrypted(" + data + ")";// 调用被装饰对象的Write方法stream_->Write(encryptedData);}
};

动态组合调用流程

int main() {// 创建基础对象Stream* fileStream = new FileStream();// 添加压缩功能Stream* compressedStream = new CompressedStream(fileStream);// 添加加密功能Stream* encryptedStream = new EncryptedStream(compressedStream);// 执行写入操作encryptedStream->Write("Hello, World!");// 释放资源(建议使用智能指针)delete encryptedStream;return 0;
}

调用流程图示

Client EncryptedStream CompressedStream FileStream Write("Hello, World!") 数据加密 ->> "Encrypted(Hello, World!)" Write("Encrypted(...)") 数据压缩 ->> "Compressed(Encrypted(...))" Write("Compressed(...)") 写入文件 Client EncryptedStream CompressedStream FileStream

输出结果:

Writing to file: Compressed(Encrypted(Hello, World!))

4. 装饰器模式与组合模式的区别

特性装饰器模式组合模式
核心目的动态扩展对象功能构建树形结构
对象关系1:1 的装饰关系1:N 的父子关系
调用方式链式调用递归调用
典型应用场景GUI控件装饰、IO流增强文件系统、组织架构
装饰器模式
组件
装饰器
具体装饰器A
具体装饰器B
组合模式
组件
叶子节点
组合节点
子组件1
子组件2

(装饰器继承组件,又包含组件)


5. 总结

装饰器模式关键点

特性描述
设计模式名称装饰器模式(Decorator Pattern)
核心思想通过继承和组合动态扩展对象功能
优点- 避免继承的类爆炸
- 动态、灵活地添加功能
- 符合开闭原则
适用场景需要动态扩展对象功能,且功能可以独立组合

代码优化建议

  • 使用 std::unique_ptrstd::shared_ptr 替代原始指针,避免内存泄漏
  • 对于复杂装饰链,考虑使用工厂模式创建装饰器组合
  • 在C++11/14中可使用模板装饰器实现类型安全的装饰逻辑
// 示例:模板装饰器
template <typename T>
class DecoratorTemplate : public T {
protected:T* component_;
public:DecoratorTemplate(T* component) : component_(component) {}void Operation() override {component_->Operation();}
};

相关文章:

  • 新手怎么做网站企业如何进行宣传和推广
  • 有专业做网站的吗网站公司2023年东莞疫情最新消息
  • 网站建设安全问题如何推广网上国网
  • 自己做网站选什么好站长网站查询
  • 建立网站英文龙岗网络公司
  • 毕业设计论文网seo服务建议
  • iPhone越狱基本流程
  • 【CMake入门学习教程】bash语句示例注解
  • 60页PPT实战方案 | 大数据决策分析平台建设全流程路径图
  • Bright Data亮数据 MCP + N8N x AI 新闻编辑:基于亮数据,数据采集到观点摘要工作流自动化实践
  • “Ubuntu 18.04.6 LTS“ 配置网卡静态IP
  • 数据赋能(324)——安全与合规——所有权
  • 实战 X-AnyLabeling:构建高效自动标注系统的工程实践
  • 2012_2NOIP 国王游戏 [贪心+排序+高精]
  • java 对接ETH(以太坊) 交易相关资料
  • 跟着AI学习C#之项目实践Day7
  • 在uni-app build的index.html 中加入 <mate,和title 等标签内容 内容
  • 《大模型 Agent 应用实战指南》第2章:商业目标与 Agent 能力边界定义
  • 【评估指标】MAP@k (目标检测)
  • 探索解析C++ STL中的 list:双向链表的高效实现与迭代器
  • Linux学习笔记:PCIe内核篇(3):DPC服务
  • 浪潮存储单卷单LUN不能超过64T、128T解决方法
  • 领域驱动设计(DDD)【13】之重构中的坏味道:深入理解依恋特性(Feature Envy)与表意接口模式
  • 深入浅出:RocketMQ与Kafka的双剑合璧,实现高可用与高吞吐
  • 计算机网络-----详解HTTP协议
  • 用Python做一个手机镜头