当前位置: 首页 > 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();}
};
http://www.lryc.cn/news/574983.html

相关文章:

  • python3文件操作
  • Node.js特训专栏-实战进阶:8. Express RESTful API设计规范与实现
  • python的智慧养老院管理系统
  • klayout db::edge 里的 crossed_by_point 的坑点
  • mbedtls ssl handshake error,res:-0x2700
  • 从零开始的云计算生活——第二十三天,稍作休息,Tomcat
  • Excel数据转SQL语句(增删改查)
  • 阿里云Web应用防火墙3.0使用CNAME接入传统负载均衡CLB
  • DDNS-GO 使用教程:快速搭建属于自己的动态域名解析服务(Windows 版)
  • 大语言模型的通用局限性与全球技术演进
  • React Native【实战范例】账号管理(含转换分组列表数据的封装,分组折叠的实现,账号的增删改查,表单校验等)
  • 【版本控制教程】如何使用Unreal Engine 5 + UE源代码控制(Perforce P4)
  • 【GPU RAM】实时监控GPU内存分配(一)
  • 微信小程序中scss、ts、wxml
  • 如何在 Manjaro Linux 上安装 Docker 容器
  • 云计算-Azure Functions :构建事件驱动的云原生应用报告
  • 《Effective Python》第十章 健壮性——警惕异常变量消失的问题
  • Encoder-only PLM RoBERTa ALBERT (BERT的变体)
  • 【大模型学习 | 量化】pytorch量化基础知识(1)
  • webpack5 css-loader 配置项中的modules
  • 华为云Flexus+DeepSeek征文|基于Dify+ModelArts打造智能客服工单处理系统
  • 设计模式精讲 Day 13:责任链模式(Chain of Responsibility Pattern)
  • 告别Excel地狱!用 PostgreSQL + ServBay 搭建跨境电商WMS数据中枢
  • 华为运维工程师面试题(英语试题,内部资料)
  • 数据库系统总结
  • AI+智慧高校数字化校园解决方案PPT(34页)
  • 【开源解析】基于PyQt5的智能费用报销管理系统开发全解:附完整源码
  • 博图SCL语言中 RETURN 语句使用详解
  • Harmony中的HAP、HAR、HSP区别
  • 《推荐技术算法与实践》