组合模式-C++实现

news2025/2/26 7:22:25

组合模式是一种结构型设计模式,它允许我们将对象组织成树状结构,并以递归的方式处理它们。该模式通过将单个对象和组合对象统一对待,使得客户端可以以一致的方式处理对象集合。

组合模式中有两种角色:组合和组件。组件就是叶子节点,它们没有子组件。组合是包含其他组件的容器节点,可以包含子组合或者叶子节点。

组合模式的核心思想是将对象组织成树状结构,其中单个对象和组合对象都实现了相同的接口或者继承相同的抽象类,这样可以使客户端以递归的方式处理整个对象树,不需要关心处理的节点是叶子节点还是组合节点。

举例:

我们现在要实现一个文件系统,文件系统下有多个目录或者文件,每个目录都会有多个目录和文件。

#pragma once

#include <iostream>
#include <memory>
#include <vector>

// 抽象类
class IFileSystem
{
public:

	virtual ~IFileSystem() {}

	virtual void Display() = 0;
};

// 文件,也就是叶子节点
class File
	: public IFileSystem
{
public:

	File(const std::string& _fileName)
		: fileName_(_fileName)
	{}

	virtual void Display() override
	{
		std::cout << fileName_ << std::endl;
	}

private:

	std::string fileName_;
};

// 目录,也就是组合节点
class Directory
	: public IFileSystem
{
public:

	Directory(const std::string _directoryName)
		: directoryName_(_directoryName)
	{}

	void AddComponment(std::shared_ptr<IFileSystem> _componment)
	{
		components_.emplace_back(_componment);
	}

	virtual void Display() override
	{
		std::cout << directoryName_ << std::endl;

		// 递归处理子节点
		for (auto it : components_)
			it->Display();
	}

private:

	// 目录名字
	std::string directoryName_;

	// 子节点
	std::vector<std::shared_ptr<IFileSystem>> components_;
};

在这个示例中,FileSystemComponent 是一个抽象基类,定义了所有文件系统组件需要实现的操作。File 是一个叶子节点类,代表文件对象,它实现了 Display 方法来显示文件名。Directory 是一个组合节点类,代表目录对象,它除了实现 Display 方法外,还可以通过 AddComponent 方法添加子节点。

不同的是在组合节点目录中,我们有一个存放子节点的容器components_,它存放的就是该目录下的所有组合节点或者叶子节点,以便可以递归处理它们。

测试:

void TestComponment()
{
	// 创建文件系统
	std::shared_ptr<Directory> root = std::make_shared<Directory>("Root");
	// 创建两个目录
	std::shared_ptr<Directory> sub1 = std::make_shared<Directory>("目录1");
	std::shared_ptr<Directory> sub2 = std::make_shared<Directory>("目录2");
	// 创建三个文件
	std::shared_ptr<File> file1 = std::make_shared<File>("文件1");
	std::shared_ptr<File> file2 = std::make_shared<File>("文件2");
	std::shared_ptr<File> file3 = std::make_shared<File>("文件3");

	// 创建树结构
	root->AddComponment(sub1);
	root->AddComponment(sub2);

	// 目录1下面有一个文件
	sub1->AddComponment(file1);
	// 目录2下面有两个文件
	sub2->AddComponment(file2);
	sub2->AddComponment(file3);

	root->Display();
}

测试代码中,我们创建了一个根节点root,它下面有两个目录,其中目录1里有一个文件文件1目录2有两个文件文件2文件3

输出:

Root
目录1
文件1
目录2
文件2
文件3

我们可以看到系统依次输出目录和文件名,它们的树状结构是这样的:
在这里插入图片描述
组合模式遵循以下设计原则:

1、单一职责原则 (Single Responsibility Principle):文件类只负责输出自己的文件名,目录类负责输出自己的目录名和其子节点的所有名称,即每个类应该只有一个责任。

2、开闭原则 (Open-Closed Principle):再给这个文件系统中添加一个组合节点或者子节点我们只需要添加像文件或者目录这样的类即可,即系统应该对扩展开放,对修改关闭。

3、接口隔离原则 (Interface Segregation Principle):客户端没有依赖抽象接口,即客户端不应该依赖于它不需要使用的接口。

4、依赖倒置原则 (Dependency Inversion Principle):文件和目录都依赖抽象接口,即高层模块不应该依赖于低层模块,两者都应该依赖于抽象。

优点:

1、简化客户端代码:客户端可以一致地使用单个对象或组合对象,而不需要区分它们之间的差异。

2、灵活性和可扩展性:可以很容易地增加新的组件,而不会影响现有的组件。

3、对象层次结构的一致性:组合模式让单个对象和组合对象具有相似的操作,使得整个对象层次结构更加统一。

缺点:

1、可能会加重系统的复杂性:在一些场景下,使用组合模式可能会导致系统变得更加复杂,特别是在对象层次结构比较庞大时。

2、可能会降低运行效率:由于组合模式需要通过递归来操作对象层次结构,可能会导致一些性能损耗。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1278671.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

三轴加速度计LIS2DW12开发(2)----基于中断信号获取加速度数据

三轴加速度计LIS2DW12开发.2--轮基于中断信号获取加速度数据 概述视频教学样品申请生成STM32CUBEMX串口配置IIC配置CS和SA0设置INT1设置串口重定向参考程序初始换管脚获取ID复位操作BDU设置开启INT1中断设置传感器的量程配置过滤器链配置电源模式设置输出数据速率中断判断加速…

常用数据预处理方法 python

常用数据预处理方法 数据清洗缺失值处理示例删除缺失值插值法填充缺失值 异常值处理示例删除异常值替换异常值 数据类型转换示例数据类型转换在数据清洗过程中非常常见 重复值处理示例处理重复值是数据清洗的重要步骤 数据转换示例 数据集成示例数据集成是将多个数据源合并为一…

基于Intel Ai Analytics Toolkit 及边缘计算的溶氧预测水产养殖监测方案

基于AI的淡水养殖水质溯源、优化系统方案 前言一、关键需求及方案概述二、方案设计预测机制LSTM 模型基于intel AI 的时序水质分析模型与分类模型优化 三、实战分析1、方案简述2、数据分析预处理特征类型处理特征分布分析 3、特征构造4、特征选择过滤法重要性排序 5.构建LSTM模…

Android drawable layer-list右上角红点,xml布局实现,Kotlin

Android drawable layer-list右上角红点&#xff0c;xml布局实现&#xff0c;Kotlin <?xml version"1.0" encoding"utf-8"?> <layer-list xmlns:android"http://schemas.android.com/apk/res/android"><itemandroid:id"id…

mfc项目设置软件版本

//上面设置的版本通过下面的代码可以获取到 TSTRING CVersion::GetSoftVersion() {TSTRING strVer _T("");TCHAR szPath[MAX_PATH] _T("");memset(szPath, 0, sizeof(szPath));::GetModuleFileName(NULL, szPath, sizeof(szPath));//得到本程序的目录UIN…

品优购:主体页,列表页,注册页

目录 main部分 recom推荐部分 新建列表list.html和list.css 创建register.html 和register.css main部分 focus焦点图通过ul和li框住img&#xff0c;右侧分为三栏 第一栏newsflash盒子&#xff0c;首先边框news-hd只写bottom&#xff0c;线条为dotted&#xff1b;然后news…

clickhouse -- clickhouse解析复杂JSON数组

举例 - 查数据 select _id,doctorId,patientId,diagnosisList from patient_disease final where diagnosisList is not null limit 3;- 解析数组 SELECT _id,doctorId,patientId,visitParamExtractRaw(diagnosisList,diagnosisName) FROM patient_disease final where _id …

甄知黄建华:从“天赋平平”到IT行业“六边形战士”,探索出企业数智化转型的“强IT”之路

本期我们先抛开人物和主体不表&#xff0c;从大环境开始谈起。随着科技的快速发展和全球商业环境的不断变化&#xff0c;中国企业对灵活性、创新性、全球化和效率的需求是迫切的&#xff0c;进行数字化转型来支撑企业的业务变革、组织优化已是业界共识。如何根据企业的实际情况…

【论文解读】NuScenes-QA:自动驾驶场景的多模态视觉问答基准

来源&#xff1a;投稿 作者&#xff1a;橡皮 编辑&#xff1a;学姐 论文链接&#xff1a;https://arxiv.org/pdf/2305.14836.pdf 开源代码&#xff1a;https://github.com/qiantianwen/NuScenes-QA 摘要&#xff1a; 我们在自动驾驶背景下引入了一种新颖的视觉问答&#xf…

2022年9月6日 Go生态洞察:Go的漏洞管理新支持

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

c语言:整数与浮点数在内存中的存储方式

整数在内存中的存储&#xff1a; 在计算机内存中&#xff0c;整数通常以二进制形式存储。计算机使用一定数量的比特&#xff08;bit&#xff09;来表示整数&#xff0c;比如32位或64位。在存储整数时&#xff0c;计算机使用补码形式来表示负数&#xff0c;而使用原码形式来表示…

canvas基础:绘制圆弧、圆形

canvas实例应用100 专栏提供canvas的基础知识&#xff0c;高级动画&#xff0c;相关应用扩展等信息。 canvas作为html的一部分&#xff0c;是图像图标地图可视化的一个重要的基础&#xff0c;学好了canvas&#xff0c;在其他的一些应用上将会起到非常重要的帮助。 文章目录 arc…

Python练习题(一)

&#x1f4d1;前言 本文主要是【Python】——Python练习题的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304;每日一句&am…

权限的树形列表展示——基于APEX FancyTree Select

select distinct (o.PERMISSION_ID) as id, --数据ido.PARENT_PERMISSION_ID as PARENT_ID, --父ido.PERMISSION_NAME as title, --显示的标题o.PERMISSION_ID as VALUE, --标题对应的值1 as TYPE,casewhen (select cou…

TwinCAT3一个PLC设备里多个程序工程之间通讯

目录 1、创建TwinCAT3工程&#xff0c;再分别创建两个PLC程序工程 2、PLC1工程中添加如下代码&#xff0c;然后编译重新生成PLC1工程 3、PLC2工程中添加如下代码&#xff0c;然后编译重新生成PLC2工程 4、变量关联 5、一个PLC运行多个PLC工程设置 7、工程下载链接 1、创建…

vscode 调试jlink

文章目录 软件使用说明1、启动GDB Server2、下载gdb3、vscode配置4、调试 软件 vscodejlink - (JLinkGDBServer.exe)gcc-arm-none-eabi-10-2020-q4-major (arm-none-eabi-gdb.exe) 使用说明 vscode通过TCP端口调用JLinkGDBServer通过jlink连接和操作设备&#xff0c;vscode不…

Matlab 加权均值质心计算(WMN)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 思路很简单,即将之前的均值中心,引入相关的权重函数(通常与距离有关),以此为每个点进行赋权,最后即可得到一个加权均值中心: 二、实现代码 %% ********<

Vue3+nuxt+ts项目引入高德地图API实现步骤

看了好多相关的文章都没有完全贴合选用Vue3nuxtts框架的&#xff0c;也不太靠谱&#xff0c;只好自己踩坑实现了 首先去高德开放平台用自己的账号申请一个key&#xff0c;位置如下&#xff0c;申请好后保存好生成的key 我们使用vuemap/vue-amap&#xff0c;一个高德地图2.0版本…

百度下拉词挖掘工具,百度下拉词挖掘获取软件

百度下拉词挖掘工具 百度下拉词挖掘工具&#xff0c;作为站长和SEO人员必备的工具之一&#xff0c;有着令人瞩目的功能。它能够追踪用户在百度搜索栏中输入关键词时&#xff0c;百度自动为用户推荐的下拉关键词。这一推荐不仅仅是用户搜索历史的体现&#xff0c;更是一种市场需…

电源需要考虑的因素

做产品的都离不开电源&#xff0c;产品出问题也首先检查供电是否正常。今天给大家分享的是做好一个电源需要考虑哪些因素。 一&#xff0e; 描述输入电压影响输出电压几个指标形式 1&#xff0e; 稳压系数 A&#xff0e;稳压系数&#xff1a;表示负载不变时&#xff0c;稳压电源…