【设计模式】组合模式

第11章 组合模式

11.1 一个基本的目录内容遍历范例

组合模式用于处理树形结构数据,如操作系统目录。以下是目录遍历的非组合模式实现:

在这里插入图片描述

文件类定义

class File {
public:File(string name) : m_sname(name) {}void ShowName(string lvlstr) {cout << lvlstr << "-" << m_sname << endl; // 用"-"表示文件}
private:string m_sname;
};

目录类定义

#include <list>
using namespace std;class Dir {
public:Dir(string name) : m_sname(name) {}void AddFile(File* pfile) { m_childFile.push_back(pfile); }void AddDir(Dir* pdir) { m_childDir.push_back(pdir); }void ShowName(string lvlstr) {cout << lvlstr << "+" << m_sname << endl; // 用"+"表示目录lvlstr += "    "; // 缩进4个空格// 遍历文件for (auto iter = m_childFile.begin(); iter != m_childFile.end(); ++iter)(*iter)->ShowName(lvlstr);// 递归遍历子目录for (auto iter = m_childDir.begin(); iter != m_childDir.end(); ++iter)(*iter)->ShowName(lvlstr);}private:string m_sname;list<File*> m_childFile;list<Dir*> m_childDir;
};

主函数测试

int main() {// 1. 创建节点Dir* root = new Dir("root");File* f1 = new File("common.mk"), *f2 = new File("config.mk"), *f3 = new File("makefile");Dir* app = new Dir("app"), *signal = new Dir("signal"), *include = new Dir("include");File* f4 = new File("nginx.c"), *f5 = new File("ngx_conf.c"), *f6 = new File("ngx_signal.c");File* f7 = new File("ngx_func.h"), *f8 = new File("ngx_signal.h");// 2. 构建树结构root->AddFile(f1)->AddFile(f2)->AddFile(f3);root->AddDir(app)->AddFile(f4)->AddFile(f5);root->AddDir(signal)->AddFile(f6);root->AddDir(include)->AddFile(f7)->AddFile(f8);// 3. 遍历输出root->ShowName("");// 4. 释放资源(略)return 0;
}

输出结果

+root-common.mk-config.mk-makefile+app-nginx.c-ngx_conf.c+signal-ngx_signal.c+include-ngx_func.h-ngx_signal.h

11.2 使用组合模式改造范例

抽象组件类

class FileSystem {
public:virtual void ShowName(int level) = 0;virtual int Add(FileSystem* pfs) = 0;virtual int Remove(FileSystem* pfs) = 0;virtual ~FileSystem() {}
};

叶子组件(文件)

class File : public FileSystem {
public:File(string name) : m_sname(name) {}void ShowName(int level) override {cout << string(level*4, ' ') << "-" << m_sname << endl;}int Add(FileSystem* pfs) override { return -1; } // 文件不能添加子节点int Remove(FileSystem* pfs) override { return -1; }
private:string m_sname;
};

树枝组件(目录)

#include <list>
using namespace std;class Dir : public FileSystem {
public:Dir(string name) : m_sname(name) {}void ShowName(int level) override {cout << string(level*4, ' ') << "+" << m_sname << endl;for (auto& child : m_child)child->ShowName(level + 1);}int Add(FileSystem* pfs) override { m_child.push_back(pfs); return 0; }int Remove(FileSystem* pfs) override { m_child.remove(pfs); return 0; }private:string m_sname;list<FileSystem*> m_child;
};

改进后主函数

int main() {// 创建节点(使用基类指针)FileSystem* root = new Dir("root");auto add = [](FileSystem* parent, FileSystem* child) { parent->Add(child); };add(root, new File("common.mk"));add(root, new File("config.mk"));add(root, new File("makefile"));auto app = new Dir("app");add(root, app);add(app, new File("nginx.c"));add(app, new File("ngx_conf.c"));// 其他节点添加(类似)...root->ShowName(0); // 从根节点开始遍历return 0;
}

11.3 组合模式核心概念

模式定义

将对象组织成树形结构,以统一处理单个对象(叶子)和组合对象(树枝),实现部分-整体层次关系的一致操作。

UML 图

继承
继承
包含
1
*
FileSystem
+ShowName()
+Add()
+Remove()
File
+ShowName()
+Add()
+Remove()
Dir
-m_child
+ShowName()
+Add()
+Remove()
角色说明示例类
Component抽象组件,定义公共接口FileSystem
Leaf叶子节点,无子女File
Composite树枝节点,包含子节点(叶/枝)Dir

关键特性

  1. 递归遍历:通过Composite的子节点列表实现树形递归
  2. 接口统一:客户端无需区分叶节点与枝节点
  3. 开闭原则:新增节点类型时只需扩展Component子类

11.4 透明模式 vs 安全模式

透明组合模式

  • 特点:在抽象组件中声明所有接口(包括管理子节点的方法)
  • 优点:客户端代码统一,完全面向抽象编程
  • 缺点:叶子节点需实现无意义的方法(如Add

安全组合模式

// 抽象组件(无管理子节点方法)
class FileSystem {
public:virtual void ShowName(int level) = 0;virtual bool IsComposite() { return false; } // 安全检查
};// 树枝组件(单独声明管理方法)
class Dir : public FileSystem {
public:void Add(FileSystem* pfs) { /* ... */ }bool IsComposite() override { return true; }
};
  • 特点:管理子节点的方法仅在Composite中定义
  • 优点:避免叶子节点误用
  • 缺点:客户端需区分节点类型

UML

继承
继承
包含(通过 m_child)
1
*
FileSystem
+ShowName()
File
+ShowName()
Dir
-m_child
+ShowName()
+Add()
+Remove()
+GetChild()

11.5 组合模式应用场景

1. 公司组织结构

class Organization : public FileSystem {
public:virtual int GetEmployeeCount() = 0;
};class Department : public Organization { /* 叶子节点 */ };
class Branch : public Organization { /* 树枝节点,含子部门/分公司 */ };

在这里插入图片描述

2. 图形编辑器

class Graphic {
public:virtual void Draw() = 0;
};class Circle : public Graphic { /* 叶子:绘制圆形 */ };
class Group : public Graphic { /* 树枝:包含多个图形 */ };

在这里插入图片描述

包含(通过 m_child)
1
*
Graphic
-m_child
+Draw()
+Add()
+Remove()
Line
+Draw()
+Add()
+Remove()
Rectangle
+Draw()
+Add()
+Remove()
Circle
+Draw()
+Add()
+Remove()
Text
+Draw()
+Add()
+Remove()
Picture
+Draw()
+Add()
+Remove()

3. 杀毒软件

class File : public FileSystem {
public:virtual void ScanVirus() = 0;
};class ExeFile : public File { /* 特殊处理可执行文件 */ };
class Folder : public File { /* 目录扫描 */ };
继承
继承
继承
m_child
0..*
«abstract»
FileSystem
+KillVirus()
+Add()
+Remove()
ExecutableFile
+KillVirus()
+Add()
+Remove()
CommonFile
+KillVirus()
+Add()
+Remove()
Dir
-m_child: list<FileSystem>
+KillVirus()
+Add()
+Remove()

总结:组合模式通过树形结构和统一接口,简化了分层数据的操作,是处理“部分-整体”关系的核心模式。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DSP28335 eCAN(增强型控制器局域网)

一、概述 1.1 特征 can协议2.0 ,高达1Mbps32个邮箱 1)—可配置接收或发送—可配置标准或扩展标识符—接收标识符屏蔽功能—支持数据和远程帧—支持0到8字节的数据帧—在接收和发送的消息上使用32位时间戳(发送接收计时器)—接收新消息保护—允许动态可编程的发送消息优先…

现代控制原理

一、在状态空间中&#xff0c;建立控制系统的数学模型 如&#xff1a;有单输入&#xff08;U)--单输出&#xff08;Y)控制系统&#xff0c;其状态方程和输出方程如下图&#xff1a; 二、画状态结构图 将上述状态方程转化为状态结构图有&#xff1a; 三、高阶控制系统的状态方…

【Git】基础使用

Git基础使用 基础配置工作区-暂存区-版本库添加文件修改文件版本回退撤销修改删除文件分支管理强制删除分支 基础配置 初始化仓库&#xff1a; git init # 此时就会生成一个 .git 的文件夹&#xff0c;切勿修改或删除文件夹里的内容配置仓库——名字&#xff1a; git config…

系统与网络安全------网络应用基础(2)

资料整理于网络资料、书本资料、AI&#xff0c;仅供个人学习参考。 交换机 认识交换机 交换机&#xff0c;Switch 用户将多台计算机/交换机连接在一起&#xff0c;组建网络 交换机负责为其中任意两台计算机提供独享线路进行通信 非网管型交换机 即插即用交换机 即插即用&…

【xiaozhi赎回之路-2:语音可以自己配置就是用GPT本地API】

固件作用 打通了网络和硬件的沟通 修改固件实现【改变连接到小智服务器的】 回答逻辑LLM自定义 自定义了Coze&#xff08;比较高级&#xff0c;自定义程度比较高&#xff0c;包括知识库&#xff0c;虚拟脚色-恋人-雅思老师-娃娃玩具{可能需要使用显卡对开源模型进行微调-产…

蓝桥杯——嵌入式学习日记

因为lED和LCD共用PC8~PC15引脚&#xff0c;要通过锁存&#xff08;LE&#xff09;和&#xff08;GPIOC->ODR&#xff09;来避免LED和LCD引脚冲突 修改点: main.c中&#xff0c;GPIO初始化引脚后&#xff0c;LE&#xff08;PD2引脚低电平锁存&#xff0c;退出透明模式&…

Liunx系统Microsoft SQL Server数据库还原

1.确认Linux系统已安装SQLServer服务并启动 2.在Windows中使用SSMS连接原数据库与Linux远程数据库服务 3.备份 成功备份如下 4.上传bak文件到远程Linux服务器 登陆Linux服务并创建数据库文件夹 退出Linux服务

【学习资源】多元时序分析问题和时序图模型

工业数据分析领域中&#xff0c;多元时序数据分析是一个广泛的问题。今天和大家简单介绍多元时序预测、聚类、分类、时序图模型和相应的深度学习库。 图片来源&#xff1a;https://www.researchgate.net/publication/349207209_Multivariate_Time-Series_Anomaly_Detection_via…

QT二 QT使用generate form 生成常用UI,各种UI控件

一 。没有使用general form 和 使用 general form 后&#xff0c;file层面和代码层面的不同比较 file层面的不同 代码层面的不同&#xff0c; 在 使用了general form之后&#xff0c;在主界面的构造方法中&#xff0c;使用ui->setupUi(this),就完成了所有UI的处理。 而之…

Haption力反馈遥操作机器人:6自由度高精度技术,定义远程操作新标准

Haption在力反馈遥操作机器人技术领域展现了强大的创新能力。其核心技术——力反馈技术&#xff0c;通过提供高度逼真的触觉反馈&#xff0c;显著提升了远程操作的精确性与用户体验。这种技术在工业、医疗等高要求场景中表现出色&#xff0c;同时也为科研和教育领域提供了有力支…

魔塔社区的torch_empty错误问题的解决办法

前言 我在运行魔塔社区&#xff08;modelscope&#xff09;的ZhipuAI/chatglm3-6b模型&#xff08;智谱&#xff09;的实例程序的时候&#xff0c;碰到了一个奇怪的错误&#xff08;torch.empty&#xff09;&#xff0c;我尝试解决了一下。 &#xff08;当前采用的Python版本…

全面了解 Cookies、Session 和 Token

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…

51c自动驾驶~合集26

我自己的原文哦~ https://blog.51cto.com/whaosoft/11968755 #大模型/Sora/世界模型之间是什么关系 1 什么是大模型 人工智能大模型&#xff08;Artificial Intelligence Large Model&#xff0c;简称AI大模型&#xff09;是指具有庞大的参数规模和复杂程度的机器学习模…

分布式环境下的重复请求防护:非Redis锁替代方案全解析

目录 引言 方案一&#xff1a;前端防护策略 方案二&#xff1a;后端协同控制 方案三&#xff1a;流量控制与过滤 滑动窗口限流 布隆过滤器 方案四&#xff1a;基于框架的实践方案 多层防护策略与最佳实践 总结 引言 在Web应用开发中&#xff0c;防止用户重复点…

4.1 C#获取目录的3个方法的区别

C#中常用有如下3个获取目录的方式如下 1.Directory.GetCurrentDirectory():获取当前工作目录&#xff0c;工作目录可能被用户或其他代码修改。尽量少用。&#xff08;似乎只要在运行中使用另存为或者打开某个文件夹&#xff0c;当前工作目录就修改&#xff09; 2.Application…

【漏洞复现】Next.js中间件权限绕过漏洞 CVE-2025-29927

什么是Next.js&#xff1f; Next.js 是由 Vercel 开发的基于 React 的现代 Web 应用框架&#xff0c;具备前后端一体的开发能力&#xff0c;广泛用于开发 Server-side Rendering (SSR) 和静态站点生成&#xff08;SSG&#xff09;项目。Next.js 支持传统的 Node.js 模式和基于边…

MCU-芯片时钟与总线和定时器关系,举例QSPI

时钟源&#xff1a; 时钟源为系统时钟提供原始频率信号&#xff0c;系统时钟则通过&#xff08;分频、倍频、选择器&#xff09;成为整个芯片的“主时钟”&#xff0c;驱动 CPU 内核、总线&#xff08;AHB、APB&#xff09;及外设的运行。 内部时钟源&#xff1a; HSI&#x…

使用 ByteDance 的 UI-TARS Desktop 探索 AI 驱动的 GUI 自动化新前沿

文章目录 UI-TARS Desktop 是什么&#xff1f;技术亮点应用场景如何快速上手&#xff1f;与其他技术的对比未来展望结语 随着人工智能技术的快速发展&#xff0c;AI 正在从单纯的文本生成和图像识别迈向更复杂的交互场景。ByteDance 近期推出的 UI-TARS Desktop&#xff08;基于…

DockerFile制作镜像(Dockerfile Creates an Image)

DockerFile制作镜像 hub.docker.com 搜索到的 Redis官方镜像&#xff0c;提示我们可以创建自己的 DockerFile 来添加 redis.conf 文件&#xff1a; 于是&#xff0c;我准备进行首次 DockerFile 的制作尝试。 一、准备工作 1.1 下载 redis.conf 我的方案是从 GitHub 上下载 …

C++List模拟实现|细节|难点|易错点|全面解析|类型转换|

目录 1.模拟代码全部 2.四大块代码理解 1.最底层&#xff1a;ListNode部分 2.第二层&#xff1a;ListIterator部分 3.第三层&#xff1a;ReserveListIterator部分 4最终层&#xff1a;List 1.模拟代码全部 using namespace std; template<class T> struct ListNode …