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

篇八:装饰器模式:动态增加功能

篇八:“装饰器模式:动态增加功能”

开始本篇文章之前先推荐一个好用的学习工具,AIRIght,借助于AI助手工具,学习事半功倍。欢迎访问:http://airight.fun/。

另外有2本不错的关于设计模式的资料,分享出来与大家学习参考。
链接:https://pan.baidu.com/s/1RmhQF_o1CdK8U7s5KeILog?pwd=xc6d
提取码:xc6d

设计模式是软件开发中的重要组成部分,装饰器模式是结构型设计模式中的一种。装饰器模式旨在动态地为对象增加额外的功能,而无需修改其结构。通过装饰器模式,我们可以在不影响现有代码的情况下,灵活地扩展对象的功能。在C++中,装饰器模式广泛应用于需要动态增加对象功能的场景,让我们一起分析其作用和实现方式,并指导读者在C++中如何应用装饰器模式。

1. 装饰器模式的作用和实现方式:
装饰器模式是结构型设计模式,其作用在于动态地为对象增加额外的功能,而不影响其结构。装饰器模式通过创建装饰器类来包装原有类,从而实现对原有类的功能扩展。装饰器模式是继承关系的替代方案,避免了类爆炸的问题。

装饰器模式的实现方式如下:

  1. 定义抽象组件类:抽象组件类定义了装饰器和原有类的共同接口。
  2. 创建具体组件类:具体组件类实现抽象组件类的接口,表示原有类。
  3. 创建抽象装饰器类:抽象装饰器类继承自抽象组件类,并包含一个对抽象组件的引用。
  4. 创建具体装饰器类:具体装饰器类继承自抽象装饰器类,用于包装具体组件类,并在其功能上进行扩展。

2. 在C++中应用装饰器模式动态增加对象功能:

a. 定义抽象组件类:

// Component.h
class Component {
public:virtual ~Component() {}virtual void operation() const = 0;
};

b. 创建具体组件类:

// ConcreteComponent.h
#include <iostream>
#include "Component.h"class ConcreteComponent : public Component {
public:void operation() const override {std::cout << "ConcreteComponent operation" << std::endl;}
};

c. 创建抽象装饰器类:

// Decorator.h
#include "Component.h"class Decorator : public Component {
public:Decorator(Component* component) : component_(component) {}virtual ~Decorator() {}void operation() const override {if (component_) {component_->operation();}}protected:Component* component_;
};

d. 创建具体装饰器类:

// ConcreteDecoratorA.h
#include <iostream>
#include "Decorator.h"class ConcreteDecoratorA : public Decorator {
public:ConcreteDecoratorA(Component* component) : Decorator(component) {}void operation() const override {Decorator::operation();addedBehavior();}void addedBehavior() const {std::cout << "ConcreteDecoratorA added behavior" << std::endl;}
};
// ConcreteDecoratorB.h
#include <iostream>
#include "Decorator.h"class ConcreteDecoratorB : public Decorator {
public:ConcreteDecoratorB(Component* component) : Decorator(component) {}void operation() const override {Decorator::operation();addedBehavior();}void addedBehavior() const {std::cout << "ConcreteDecoratorB added behavior" << std::endl;}
};

e. 使用装饰器模式:

// main.cpp
#include "ConcreteComponent.h"
#include "ConcreteDecoratorA.h"
#include "ConcreteDecoratorB.h"int main() {Component* component = new ConcreteComponent();Component* decoratorA = new ConcreteDecoratorA(component);Component* decoratorB = new ConcreteDecoratorB(decoratorA);decoratorB->operation();delete decoratorB;delete decoratorA;delete component;return 0;
}

在上述示例中,我们首先定义了抽象组件类Component,并创建了具体组件类ConcreteComponent,表示原有类。然后,我们定义了抽象装饰器类Decorator,继承自Component,并包含一个对抽象组件的引用。接着,我们创建了具体装饰器类ConcreteDecoratorAConcreteDecoratorB,继承自抽象装饰器类,用于包装具体组件类,并在其功能上进行扩展。

main.cpp中,我们创建了具体组件对象component,然后用ConcreteDecoratorA包装它,再用ConcreteDecoratorB包装它。最后,我们调用装饰器对象的operation()方法,从而实现了动态增加对象功能。

3. 装饰器模式的代码解析:

  • 装饰器模式通过创建装饰器类来包装原有类,实现了对原有类的功能扩展,同时避免了类爆炸的问题,增加了系统的灵活性和可扩展性。
  • 抽象组件类定义了装饰器和原有类的共同接口,抽象装饰器类继承自抽象组件类,并包含一个对抽象组件的引用,具体装饰器类继承自抽象装饰器类,用于包装具体组件类,并在其功能上进行扩展。

4. 总结:
装饰器模式是结构型设计模式,其作用在于动态增加对象的功能,而无需修改其结构。通过创建装饰器类来包装原有类,实现了对原有类的功能扩展,同时避免了类爆炸的问题,增加了系统的灵活性和可扩展性。

在C++中,可以通过定义抽象组件类和抽象装饰器类,以及创建具体组件类和具体装饰器类的方式来应用装饰器模式。具体组件类表示原有类,抽象装饰器类继承自抽象组件类,并包含一个对抽象组件的引用,具体装饰器类继承自抽象装饰器类,用于包装具体组件类,并在其功能上进行扩展。

使用装饰器模式时,首先创建具体组件对象,然后通过具体装饰器类对其进行包装,从而动态增加对象功能。装饰器模式允许客户端根据需求选择不同的装饰器进行组合,从而实现不同的功能组合,而无需修改原有类。

5. 总结:
装饰器模式是结构型设计模式,其作用在于动态增加对象的功能,而无需修改其结构。通过创建装饰器类来包装原有类,实现了对原有类的功能扩展,同时避免了类爆炸的问题,增加了系统的灵活性和可扩展性。在C++中,可以通过定义抽象组件类和抽象装饰器类,以及创建具体组件类和具体装饰器类的方式来应用装饰器模式。使用装饰器模式时,首先创建具体组件对象,然后通过具体装饰器类对其进行包装,从而动态增加对象功能。装饰器模式允许客户端根据需求选择不同的装饰器进行组合,从而实现不同的功能组合,而无需修改原有类。

希望本文能够帮助您更好地理解装饰器模式的作用和实现方式,并指导您在C++中应用装饰器模式来动态增加对象功能。在后续的专栏文章中,我们将继续介绍更多设计模式的知识,包括原理、详细介绍、示例代码和代码解析,帮助您深入学习和应用设计模式。

参考文献:

  • Gamma, E., Helm, R., Johnson, R., & Vlissides, J. (1994). Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley Professional.
  • C++ Core Guidelines: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines

感谢您的阅读,欢迎一起探讨,共同进步,推荐大家使用学习助手AIRight来解答学习过程中的问题,访问链接:http://airight.fun/

相关文章:

篇八:装饰器模式:动态增加功能

篇八&#xff1a;“装饰器模式&#xff1a;动态增加功能” 开始本篇文章之前先推荐一个好用的学习工具&#xff0c;AIRIght&#xff0c;借助于AI助手工具&#xff0c;学习事半功倍。欢迎访问&#xff1a;http://airight.fun/。 另外有2本不错的关于设计模式的资料&#xff0c…...

算法通关村第五关——n数之和问题解析

1. 两数之和问题 力扣第1题就是两数之和问题&#xff0c;给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那两个整数&#xff0c;并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一…...

小白到运维工程师自学之路 第七十集 (Kubernetes集群部署)

一、概述 Kubernetes&#xff08;简称K8S&#xff09;是一个开源的容器编排和管理平台&#xff0c;是由Google发起并捐赠给Cloud Native Computing Foundation&#xff08;CNCF&#xff09;管理的项目。它的目标是简化容器化应用的部署、扩展、管理和自动化操作。 以下是Kube…...

docker 部署mysql 5.6集群

docker搭建mysql的集群&#xff08;一主双从&#xff09; 1.拉取镜像 docker pull mysql:5.6 2.启动master容器 docker run -it -d --name mysql_master -p 3306:3306 --ip 192.168.162.100 \ -v /data/mysql_master/mysql:/var/lib/mysql \ -v /data/mysql_master/conf.d…...

mysql基本信息查询

1.查看mysql表的数据量 select table_schema as 数据库, table_name as 表名, table_rows as 记录数, truncate(data_length/1024/1024, 2) as 数据容量(MB), truncate(index_length/1024/1024, 2) as 索引容量(MB) from information_schema.tables order by data_length des…...

C语言初学者必读:使用for循环将数字从大到小排序并输出

在学习C语言编程的过程中&#xff0c;了解数组的输入和排序是非常基础且重要的一部分。本文将以通俗易懂的方式&#xff0c;教你如何使用for循环实现将输入的n个数字按照从大到小的顺序输出&#xff0c;帮助你逐步掌握数组的使用和排序算法。 第一步&#xff1a;获取用户输入 …...

【Vue+Element-plus】记录后台首页多echart图静态页面

一、页面效果 二、完整代码 Index.vue <template><div><div><DateTime /><!-- {{username}} --></div><el-row :gutter"20"><el-col :span"8"><div class"grid-content bg-purple"><P…...

BM5 合并k个已排序的链表 javascript

描述 合并 k 个升序的链表并将结果作为一个升序的链表返回其头节点。 数据范围&#xff1a; 示例1 输入&#xff1a; [{1,2,3},{4,5,6,7}] 返回值&#xff1a; {1,2,3,4,5,6,7}示例2 输入&#xff1a; [{1,2},{1,4,5},{6}] 返回值&#xff1a; {1,1,2,4,5,6}解题思路 利用两个…...

1.利用matlab建立符号表达式(matlab程序)

1.简述 、 1. 使用sym命令创建符号变量和表达式 语法&#xff1a; sym(‘变量’,参数) %把变量定义为符号对象 说明&#xff1a;参数用来设置限定符号变量的数学特性&#xff0c;可以选择为’positive’、’real’和’unreal’&#xff0c; ’positive’ 表示为“正、实”符…...

LVS工作环境配置

一、LVS-DR工作模式配置 模拟环境如下&#xff1a; 1台客户机 1台LVS负载调度器 2台web服务器 1、环境部署 &#xff08;1&#xff09;LVS负载调度器 yum install -y ipvsadm # 在LVS负载调度器上进行环境安装 ifconfig ens33:200 192.168.134.200/24 # 配置LVS的VIP…...

金蝶,「起舞」在大模型时代

在过去的几年时间里&#xff0c;基于EBC的平台能力&#xff0c;金蝶已经走出了一个新的进化之路&#xff0c;这条路是对自身产品竞争力的重新构建&#xff0c;也更是对企业数字化转型需求的更大程度满足。 如今&#xff0c;苍穹GPT大模型更是让这种竞争力和服务力更向前一步。…...

解决Vs Code工具开发时 保存React文件时出现乱码情况

Vs Code工具开发时 保存React文件时出现乱码情况 插件库搜索:JS-CSS-HTML Formatter 把这个插件禁用或者卸载就解决保存时出现乱码的问题了; 如果没有解决,再看下面方案! 出现乱码问题通常是因为文件的编码格式不正确。您可以尝试以下解决方法&#xff1a; 确认文件编码格式&a…...

Fastjson 使用指南

文章目录 Fastjson 使用指南0 简要说明为什么要用JSON&#xff1f;用JSON的好处是什么&#xff1f;为什么要用JSON&#xff1f;JSON好处 1 常用数据类型的JSON格式值的范围 2 快速上手2.1 依赖2.2 实体类2.3 测试类 3 常见用法3.1 序列化操作核心操作对象转换为JSON串list转换J…...

阿里云内容审核服务使用(图片审核)

说明&#xff1a;在项目中&#xff0c;我们经常会对用户上传的内容&#xff08;如文字、图片&#xff09;等资源内容进行审核&#xff0c;审核包括两方面&#xff0c;一方面是内容与描述不符&#xff0c;一方面是违反法律法规。本文介绍使用阿里提供的内容审核服务&#xff0c;…...

git撤回最近一次push操作

git push -f origin HEAD^:branch_name其中&#xff0c;branch_name 是你想要撤回 push 操作的分支的名称。 这个命令将会强制推送到远程仓库&#xff0c;将远程分支回滚到上一个提交&#xff08;HEAD^ 意味着上一个提交&#xff09;。这样做会丢失最近一次 push 的更改&#…...

2000-2022年上市公司环境不确定性(原始数据+测算代码+测算结果)

2000-2022年上市公司环境不确定性指数&#xff08;含原始数据 代码和计算结果&#xff09; 1、时间&#xff1a;2000-2022年 2、指标&#xff1a;gupiao代码、名称、日期、年份、总资产净利润率ROA、营业收入、上市日期、成立日期、行业代码、年末是否ST或PT、行业、EU未调整…...

网络基本概念

目录 一、IP地址 1. 概念 2. 格式 3. 特殊IP 二、端口号 1.概念 2. 格式 3.注意事项 三、 协议 1. 概念 2. 作用 四、协议分层 1. 网络设备所在分层 五、封装与分用 六、客户端和服务器 1. 客户端与服务器通信的过程 一、IP地址 1. 概念 IP地址主要用于标识网络主机.其他网络…...

2.安装Docker-ce

一、删除之前安装的docker(若之前未安装过&#xff0c;此步骤省略…) 进入centos根目录执行以下命令&#xff08;\ 是linux系统种命令换行符&#xff0c;如果命令过长&#xff0c;可以用\来换行&#xff09; yum remove docker \ docker-client \ docker-client-latest \ doc…...

Redis-2

Redis 持久化 Redis 为了保证效率&#xff0c;数据缓存在了内存中&#xff0c;但是会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件中&#xff0c;以保证数据的持久化。总的目的把数据保存到硬盘&#xff0c;有 RDB 和 AOF 两种。 RDB 持久化方案: RDB 是一…...

一分钟了解下Java追随和适应云原生的手段之Java Native Build(JNB)

文章首发地址 为了解决在云原生环境中&#xff0c;Java应用启动慢的问题&#xff0c;出现了很多派系&#xff0c;如拯救派&#xff0c;让应用在原有基础上启动更快&#xff08;一般都是用资源换时间&#xff09;&#xff0c;还有就是革命派&#xff0c;Java向Golang学习&#x…...

Cortex-M0中断与系统控制:从NVIC、SysTick到低功耗实战解析

1. 项目概述&#xff1a;从零开始理解Cortex-M0的中断与系统控制如果你正在接触基于ARM Cortex-M0内核的微控制器&#xff0c;比如STM32F0系列、NXP的LPC800系列&#xff0c;或者是一些国产的M0芯片&#xff0c;那么“中断”和“系统控制”这两个词&#xff0c;绝对是你绕不开的…...

6.3 节深度拆解:Hermes Agent 多 Agent 协同执行链路的 4 层设计逻辑

1. 多 Agent 协同不是“堆人”,而是建流水线:Hermes 的 4 层链路设计,本质是工程化任务分解 我第一次把三个 Hermes Agent 拉进同一个 workflow 时,以为只要给它们起好名字、连上模型、丢个需求进去,就能自动跑出结果。结果跑了三轮:第一轮,Code Agent 写完函数,Test …...

Claude code配置全流程(附带接入模型)

1.安装nodejs (Claudecode 本身是用TypeScript/JavaScript开发的命令行工具&#xff0c;需要通过Node.js运行时来执行&#xff0c;并且node.js天然集成npm,claudecode是作为npm包发布的)&#xff1a; 1.1网址&#xff1a;https://node.org.cn/ 进入后下载自己需要的系统类型就可…...

STM32串口转RS-485双机通信:硬件设计、软件驱动与调试全解析

1. 项目概述&#xff1a;从串口到485&#xff0c;双机通信的工业级实现搞嵌入式开发&#xff0c;尤其是用STM32做控制&#xff0c;串口通信&#xff08;UART&#xff09;绝对是绕不开的基础。但如果你想把两个STM32板子连起来&#xff0c;距离稍微远一点&#xff0c;或者环境里…...

别让拼写检查器坑了你的代码!Visual Studio中自定义排除字典(exclusion.dic)的完整用法

深度定制Visual Studio拼写检查&#xff1a;打造团队专属的exclusion.dic解决方案 当你在Visual Studio中看到熟悉的红色波浪线时&#xff0c;第一反应可能是代码出现了语法错误。但仔细一看&#xff0c;却发现是拼写检查器在提醒你"Hint"不是一个有效的英文单词。这…...

从51到Linux:一个嵌入式工程师的五年踩坑与填坑全记录(附避坑清单)

从51到Linux&#xff1a;一个嵌入式工程师的五年踩坑与填坑全记录&#xff08;附避坑清单&#xff09; 五年前&#xff0c;当我第一次点亮51单片机的LED灯时&#xff0c;绝没想到这条路上会有这么多隐藏的陷阱。从寄存器配置的字节对齐问题&#xff0c;到Linux驱动中的竞态条件…...

从OpenMV2到4代,我踩过的那些坑:画面变绿、传感器接触不良与内存擦除的避坑实录

从OpenMV2到4代&#xff1a;硬件升级中的稳定性挑战与实战解决方案 作为一名长期使用OpenMV系列开发视觉项目的工程师&#xff0c;我从OpenMV2一路升级到4代&#xff0c;见证了硬件性能的飞跃&#xff0c;也深刻体会到稳定性问题带来的困扰。其中最令人头疼的莫过于"画面变…...

3大核心功能解析:LilToon如何让Unity卡通渲染变得简单又专业

3大核心功能解析&#xff1a;LilToon如何让Unity卡通渲染变得简单又专业 【免费下载链接】lilToon Feature-rich shaders for avatars 项目地址: https://gitcode.com/gh_mirrors/li/lilToon 如果你正在Unity中寻找一个既能满足专业需求又容易上手的卡通渲染解决方案&am…...

OpenRGB技术架构深度解析:如何用开源统一协议打破RGB生态壁垒

OpenRGB技术架构深度解析&#xff1a;如何用开源统一协议打破RGB生态壁垒 【免费下载链接】OpenRGB Open source RGB lighting control that doesnt depend on manufacturer software. Supports Windows, Linux, MacOS. Mirror of https://gitlab.com/CalcProgrammer1/OpenRGB.…...

使用 TaoToken CLI 工具一键配置多开发环境接入参数

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 使用 TaoToken CLI 工具一键配置多开发环境接入参数 在团队协作或个人多项目开发中&#xff0c;为不同的 AI 应用工具配置 API 密钥…...