重温设计模式--1、组合模式
文章目录
- 1 、组合模式(Composite Pattern)概述
- 2. 组合模式的结构
- 3. C++ 代码示例
- 4. C++示例代码2
- 5 .应用场景
1 、组合模式(Composite Pattern)概述
- 定义:组合模式是一种结构型设计模式,它允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
- 作用:
- 简化客户端代码:客户端可以统一地处理单个对象和对象组合,而不需要区分它们是单个的叶子节点还是包含多个子节点的组合节点。例如,在一个文件系统的表示中,客户端可以用相同的方式来处理文件(叶子节点)和文件夹(组合节点),如计算文件大小或显示文件/文件夹名称等操作。
- 层次结构表示:能够很好地表示具有层次结构的对象关系。比如公司的组织结构,一个部门(组合节点)可以包含多个子部门和员工(叶子节点),通过组合模式可以清晰地构建和遍历这种层次结构。
- 灵活的对象组合:可以方便地添加新的叶子节点或组合节点,构建出复杂的对象树,并且可以动态地修改这个树的结构,而不影响客户端对树的整体操作。
2. 组合模式的结构
- 组件(Component):这是组合模式中的抽象类或接口,它为组合中的对象(包括叶子节点和组合节点)定义了统一的接口,如操作方法、添加子节点方法(对于组合节点)、删除子节点方法(对于组合节点)等。
- 叶子(Leaf):叶子节点是组合中的最底层对象,它没有子节点,实现了组件接口定义的方法,但不包含添加或删除子节点相关的操作,因为它本身不能再包含其他对象。
- 组合(Composite):组合节点代表了包含子节点的对象,它实现了组件接口,并且内部维护了一个子节点列表。它的方法实现通常是遍历子节点列表,调用子节点的相应方法来完成操作,同时也实现添加和删除子节点的方法来管理子节点列表。
3. C++ 代码示例
- 以下以一个简单的图形绘制系统为例,图形可以是简单的基本图形(如圆形、矩形,相当于叶子节点),也可以是由多个图形组成的复杂图形(相当于组合节点)。
#include <iostream>
#include <vector>// 组件抽象类
class Graphic
{
public:virtual void draw() = 0;virtual ~Graphic() {}
};// 叶子节点:圆形
class Circle : public Graphic
{
public:void draw(){std::cout << "绘制圆形" << std::endl;}
};// 叶子节点:矩形
class Rectangle : public Graphic
{
public:void draw(){std::cout << "绘制矩形" << std::endl;}
};// 组合节点:复杂图形
class ComplexGraphic : public Graphic
{
private:std::vector<Graphic*> graphics;
public:void draw(){for (std::vector<Graphic*>::iterator it = graphics.begin(); it!= graphics.end(); ++it){(*it)->draw();}}void add(Graphic* graphic){graphics.push_back(graphic);}void remove(Graphic* graphic){for (std::vector<Graphic*>::iterator it = graphics.begin(); it!= graphics.end(); ++it){if (*it == graphic){graphics.erase(it);break;}}}~ComplexGraphic(){graphics.clear();}
};int main()
{// 创建叶子节点图形Circle circle;Rectangle rectangle;// 创建组合节点图形并添加叶子节点图形ComplexGraphic complexGraphic;complexGraphic.add(&circle);complexGraphic.add(&rectangle);// 绘制组合图形,会依次绘制组合中的所有图形complexGraphic.draw();return 0;
}
在上述代码中:
Graphic
是组件抽象类,定义了draw
方法作为统一的接口,用于绘制图形。Circle
和Rectangle
是叶子节点类,它们分别实现了draw
方法来绘制具体的基本图形。ComplexGraphic
是组合节点类,内部维护了一个Graphic
指针的向量来存储子图形。draw
方法通过遍历子图形向量并调用每个子图形的draw
方法来绘制整个复杂图形,add
和remove
方法用于管理子图形列表。在main
函数中,首先创建了基本图形对象,然后创建了复杂图形对象并添加基本图形对象到其中,最后通过调用复杂图形对象的draw
方法来绘制整个组合图形,展示了组合模式在图形绘制系统中的简单应用。
4. C++示例代码2
#include<iostream>
#include<list>
#include<string>
using namespace std;
//将对象组合成树形结构以表示“部分-整体”的层次结构。
//组合模式使得用户对单个对象和组合对象的使用具有一致性class Company
{
public:Company(string name) { m_name = name; }virtual ~Company(){}virtual void Add(Company *pCom){}virtual void Show(int depth) {}
protected:string m_name;
};
//具体公司
class ConcreteCompany : public Company
{
public:ConcreteCompany(string name): Company(name) {}virtual ~ConcreteCompany() {}void Add(Company *pCom) { m_listCompany.push_back(pCom); } //位于树的中间,可以增加子树void Show(int depth){for(int i = 0;i < depth; i++){cout<<"-";}cout<<m_name<<endl;list<Company *>::iterator iter=m_listCompany.begin();for(; iter != m_listCompany.end(); iter++) //显示下层结点{(*iter)->Show(depth + 2);}}
private:list<Company *> m_listCompany;
};
//具体的部门,财务部
class FinanceDepartment : public Company
{
public:FinanceDepartment(string name):Company(name){}virtual ~FinanceDepartment() {}virtual void Show(int depth) //只需显示,无限添加函数,因为已是叶结点{for(int i = 0; i < depth; i++){cout<<"-";}cout<<m_name<<endl;}
};
//具体的部门,人力资源部
class HRDepartment :public Company
{
public:HRDepartment(string name):Company(name){}virtual ~HRDepartment() {}virtual void Show(int depth) //只需显示,无限添加函数,因为已是叶结点{for(int i = 0; i < depth; i++){cout<<"-";}cout<<m_name<<endl;}
};int main()
{Company *root = new ConcreteCompany("总公司");Company *leaf1=new FinanceDepartment("财务部");Company *leaf2=new HRDepartment("人力资源部");root->Add(leaf1);root->Add(leaf2);//分公司ACompany *mid1 = new ConcreteCompany("分公司A");Company *leaf3=new FinanceDepartment("财务部");Company *leaf4=new HRDepartment("人力资源部");mid1->Add(leaf3);mid1->Add(leaf4);root->Add(mid1);//分公司BCompany *mid2=new ConcreteCompany("分公司B");FinanceDepartment *leaf5=new FinanceDepartment("财务部");HRDepartment *leaf6=new HRDepartment("人力资源部");mid2->Add(leaf5);mid2->Add(leaf6);root->Add(mid2);root->Show(0);delete leaf1; delete leaf2;delete leaf3; delete leaf4;delete leaf5; delete leaf6;delete mid1; delete mid2;delete root;return 0;
}输出:
总公司
--财务部
--人力资源部
--分公司A
----财务部
----人力资源部
--分公司B
----财务部
----人力资源部
请按任意键继续. . .
组合模式让客户一致的使用组合结构和单个对象,他们的接口是统一透明的,这样用户就无须做判断,然后根据不同的结果去执行不同的动作了。
5 .应用场景
- 文件系统和目录结构表示
- 描述层次关系:文件系统是典型的树形层次结构,由文件(叶子节点)和文件夹(组合节点)组成。组合模式可以很好地对其进行建模。例如,在操作系统的文件管理器中,每个文件夹可以包含文件和子文件夹,使用组合模式可以用统一的方式处理文件和文件夹的操作,如计算文件夹大小(需要递归计算子文件夹和文件的大小)、显示文件和文件夹列表、复制或移动文件夹(包括其内部的所有文件和子文件夹)等操作。
- 权限管理:对于文件系统的访问权限设置,权限可以从文件夹继承到文件。通过组合模式,可以方便地为文件夹(组合节点)设置权限,并将这些权限传播给其包含的文件(叶子节点)和子文件夹,确保整个文件系统层次结构的权限一致性。
- 图形用户界面(GUI)组件层次结构
- 构建界面布局:在GUI设计中,窗口、面板(如容器面板)是组合节点,而按钮、文本框等是叶子节点。组合模式用于构建复杂的用户界面布局。例如,一个窗口可以包含多个面板,每个面板又可以包含按钮、文本框等各种控件。通过组合模式,可以方便地添加、删除或重新排列这些界面组件,并且可以对整个界面或部分组件进行统一的操作,如显示、隐藏、设置样式等。
- 事件处理和消息传递:在GUI系统中,事件(如鼠标点击、键盘输入)需要在组件层次结构中传播。组合模式可以帮助实现事件从顶层窗口向下传递到具体的叶子节点组件,或者从底层组件向上冒泡到父容器组件,从而实现合理的事件处理机制。
- 组织结构和资源管理
- 企业组织结构建模:企业的组织结构是一个层次分明的体系,包括部门(组合节点)和员工(叶子节点)。组合模式可以用于表示这种组织结构,方便进行资源分配、任务分配等操作。例如,人力资源部门可以通过组合模式表示的组织结构,为整个公司(根节点)或者某个部门(子组合节点)统一进行工资核算、培训安排等操作,这些操作可以递归地应用到部门内的所有员工(叶子节点)。
- 计算机集群资源管理:在计算机集群环境中,集群(组合节点)由多个计算节点(叶子节点)组成。通过组合模式,可以对集群资源进行统一管理,如分配任务到集群(将任务分配到具体的计算节点)、监控集群状态(包括各个计算节点的状态)、进行软件安装和更新(在集群范围内或者部分计算节点范围内)等操作。
- 游戏开发中的场景和对象管理
- 游戏场景构建:游戏场景通常包含各种游戏对象,如角色(叶子节点)、道具(叶子节点)和地形(组合节点,可能包含多个子地形区域)等。组合模式可以用于构建游戏场景,方便游戏开发者添加、删除或修改游戏场景中的对象。例如,在一个角色扮演游戏中,可以通过组合模式创建一个包含多个区域(组合节点)的大地图场景,每个区域又包含角色、道具等对象,对整个场景或者部分区域的操作(如渲染、碰撞检测等)可以通过组合模式统一进行。
- 游戏对象层次关系处理:游戏中的一些对象可能具有父子关系,如角色装备(叶子节点)与角色本身(组合节点)。通过组合模式,可以更好地处理这种对象层次关系,例如,当角色移动时,其装备也随之移动;当角色受到攻击时,其装备的属性(如防御值)可以对攻击进行响应,这种对象之间的关联和操作可以通过组合模式来清晰地实现。
相关文章:

重温设计模式--1、组合模式
文章目录 1 、组合模式(Composite Pattern)概述2. 组合模式的结构3. C 代码示例4. C示例代码25 .应用场景 1 、组合模式(Composite Pattern)概述 定义:组合模式是一种结构型设计模式,它允许你将对象组合成…...
单片机:实现SYN6288语音播报(附带源码)
单片机实现SYN6288语音播报 SYN6288是一款广泛应用于语音合成的IC,可以通过串口与单片机(如51系列、STM32等)进行通信,实现场景化的语音播报。通过连接外部存储设备(如SD卡)存储语音文件或直接通过内部语音…...
cookie,session,token 的区别
解决什么问题?Cookie(客户端存储)问题来了 Session(会话)解决的问题问题来了 token(令牌)解决的问题问题:token是无状态的如何解决? 解决什么问题? 解决http无状态的问题,说简单点就是用户身份的验证 举个例子: 张三在银行里…...

基于OpenAI Whisper AI模型自动生成视频字幕:全面解析与实战指南
在数字化时代,视频内容已成为信息传播的重要载体。然而,为视频添加字幕却是一项繁琐且耗时的工作。幸运的是,随着人工智能技术的飞速发展,特别是OpenAI Whisper模型的推出,我们有了更加高效、智能的解决方案。 一、Op…...

物理学天空的两朵乌云——量子论与相对论
物理学天空的两朵乌云——量子论与相对论 爱因斯坦的青春与科学的辉煌起点 提到爱因斯坦,我们往往会联想到一个经典的形象——乱糟糟的头发,叼着烟斗,脸上满是岁月的皱纹。然而,这张深入人心的照片并不是他科学创造力的象征。实…...

聚类之轮廓系数
Silhouette Score(轮廓系数)是用于评估聚类质量的指标之一。它衡量了数据点与同簇内其他点的相似度以及与最近簇的相似度之间的对比。 公式 对于一个数据点 i: a(i): 数据点 i 到同簇内其他点的平均距离(簇内不相似度ÿ…...

Jenkins 构建流水线
在 Linux 系统上安装 Jenkins 服务,以及配置自动化构建项目 前置准备环境:docker、docker-compose、jdk、maven 一、环境搭建 1. Jenkins 安装 (1)拉取镜像 # 安装镜像包,默认安装最新版本 docker pull jenkins/jen…...

RTK部分模糊度固定测量流程图
部分模糊度剔除常用测量: 周跳或失锁时间优先剔除;按俯仰角剔除;按浮点模糊度协方差大小剔除模糊度;按信号强度剔除卫星;...

力扣-数据结构-2【算法学习day.73】
前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向(例如想要掌握基础用法,该刷哪些题?建议灵神的题单和代码随想录)和记录自己的学习过程,我的解析也不会做的非常详细,只会提供思路和一些关…...
操作系统导论读书笔记
目录 虚拟化抽象:进程抽象:进程概念 虚拟化 抽象:进程 本章讨论操作系统提供的基本的抽象—— 进程。进程的非正式定义非常简单:进程就是运行中的程序。程序本身是没有生命周期的,它只是存在磁盘上面的一些指令&…...
基于3D-Speaker进行区分说话人项目搭建过程报错记录 | 通话录音说话人区分以及语音识别 | 声纹识别以及语音识别 | pyannote-audio
0. 研究背景 在外呼系统中,我们的后台管理系统通常要对电话录音的内容进行提取和分析。那么说到分析,我们就要对录音中的两个人的对话进行分离,然后分别分析,比如分析客户是否有合作的意愿,分析客服讲的话术是否合理&…...
如何使用流式渲染技术提升用户体验
提示:记录工作中遇到的需求及解决办法 文章目录 什么是流式渲染?Node.js 实现简单流式渲染声明式 Shadow DOM,不依赖 javascript 实现react 实现流式渲染总结提示:以下是本篇文章正文内容,下面案例可供参考 什么是流式渲染? 流式渲染主要思想是将HTML文档分块(chunk)…...
【接口自动化连载】使用yaml配置文件自动生成接口case
直接上干货撸代码,有一些是通用的工具类代码,一次性封装永久使用,期待大家的关注,一起加油!!! 配置文件 根据不同的业务需求进行配置,例如Goods服务、Order服务分开配置࿰…...
前端安全 常见的攻击类型及防御措施
1. 跨站脚本攻击(XSS) 描述:跨站脚本(XSS:Cross-Site Scripting)是一种安全漏洞,允许攻击者向网站注入恶意客户端代码。该代码由受害者执行从而让攻击者绕过访问控制并冒充用户。XSS攻击可以分…...
来道面试题——CopyOnWriteArrayList
原理 初始化时候,CopyOnWriteArrayList内部维护了一个可变数组,用于存储元素当执行数据变更操作的时候,会先创建一个原数组的副本,在副本上进行写操作,修改副本中的元素。写操作完成之后,把原数组的引用指…...

【Rust自学】5.1. 定义并实例化struct
喜欢的话别忘了点赞、收藏加关注哦,对接下来的教程有兴趣的可以关注专栏。谢谢喵!(・ω・) 5.1.1. 什么是struct struct的中文意思为结构体,它是一种自定义的数据类型,它允许程序为相关联的值命名和打包&am…...
React 生命周期完整指南
React 生命周期完整指南 1. 生命周期概述 1.1 React 16.3 之前的生命周期 初始化阶段 constructorcomponentWillMountrendercomponentDidMount 更新阶段 componentWillReceivePropsshouldComponentUpdatecomponentWillUpdaterendercomponentDidUpdate 卸载阶段 componentWil…...
python中os._exit(0) 强制关闭进程后来杀死线程
在 Python 中调用 os._exit(0) 会强制终止整个进程,包括所有正在运行的线程。以下是详细解释: os._exit(0) 的行为 立即终止进程:os._exit() 函数会立即终止当前进程,不会执行任何清理操作,如调用清理处理程序&#…...

LeetCode:257. 二叉树的所有路径
跟着carl学算法,本系列博客仅做个人记录,建议大家都去看carl本人的博客,写的真的很好的! 代码随想录 LeetCode:257. 二叉树的所有路径 给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根…...

RSICV国产芯片之CHV208
1. 芯片选型分析的对比维度 分析或者对标应用的芯片替代思路 1.1 内核/主频/存储空间支持 内核能力/指令集支持(考虑工具链兼容性); 主频:对比计算能力是否满足基本要求 存储:内存--数据搬移空间决定数据运算的…...

006网上订餐系统技术解析:打造高效便捷的餐饮服务平台
网上订餐系统技术解析:打造高效便捷的餐饮服务平台 在数字化生活方式普及的当下,网上订餐系统成为连接餐饮商家与消费者的重要桥梁。该系统以菜品分类、订单管理等模块为核心,通过前台展示与后台录入的分工协作,为管理员和会员提…...

力提示(force prompting)的新方法
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...
vscode code runner 使用python虚拟环境
转载如下: zVS Code插件Code Runner使用python虚拟环境_coderunner python-CSDN博客...
VUE混合开发用哪个PHP框架好?
在 Vue.js 主导前端的混合开发浪潮中,一个强大、灵活的后端 API 提供者至关重要。PHP 作为经久不衰的服务器端语言,拥有众多优秀框架。但哪个才是 Vue 混合开发的黄金搭档?本文将深入分析主流 PHP 框架的优劣,帮你找到最适合的那个…...

国标GB28181视频平台EasyGBS视频实时监控系统打造换热站全景可视化管理方案
一、方案背景 在城市供热体系中,换热站作为连接热源与用户的核心枢纽,其运行稳定性直接影响供热质量。面对供热规模扩大与需求升级,传统人工巡检模式暴露出效率低、响应慢、监测不足等问题。基于GB28181协议的EasyGBS视频实时监控系统&…...
Ubuntu 25.10 将默认使用 sudo-rs
非盈利组织 Trifecta Tech Foundation 报告,Ubuntu 25.10 将默认使用它开发的 sudo-rs——用内存安全语言 Rust 开发的 sudo 实现。 Ubuntu 25.10 代号 Questing Quokka,预计将于 2025 年 10 月释出,是一个短期支持版本。Sudo-rs 是 Trifect…...

【Linux系列】rsync命令详解与实践
博客目录 高效文件同步的艺术:rsync 命令详解与实践rsync 命令解析rsync 的核心优势1. 增量传输:效率的革命2. 归档模式(-a):保留文件所有属性3. 人性化输出(-h)与进度显示(--progress) 实际应用场景1. 文件备份与版本管理2. 跨设备同步3. 大…...

网络各类型(BMA,NBMA,P2P)
网络类型—基于二层(数据链路层)使用的协议不同从而导致数据包封装方式不同,工作方式也有所区别,从而对网络本身进行分类 一、网络类型分类 2. 关键差异对比 1. HDLC(高级数据链路控制协议) 协议特点&…...
[Java 基础]面向对象-封装
封装是构建健壮、可维护和安全软件的基础。 什么是封装? 想象一下你的手机。你不需要知道手机内部复杂的电路、芯片和各种组件是如何协同工作的,你只需要知道如何使用屏幕、按键或触摸操作来打电话、发短信或玩游戏。手机的内部细节被“包裹”起来&…...

从OSI到TCP/IP:网络协议的演变与作用
个人主页:chian-ocean 文章专栏-NET 从OSI到TCP/IP:网络协议的演变与作用 个人主页:chian-ocean文章专栏-NET 前言网络发展LANWAN 协议举个例子: 协议的产生背景 协议的标准化OSI模型参考OSI各个分层的作用各层次的功能简介 TCP/…...