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

重温设计模式--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方法作为统一的接口,用于绘制图形。
  • CircleRectangle是叶子节点类,它们分别实现了draw方法来绘制具体的基本图形。
  • ComplexGraphic是组合节点类,内部维护了一个Graphic指针的向量来存储子图形。draw方法通过遍历子图形向量并调用每个子图形的draw方法来绘制整个复杂图形,addremove方法用于管理子图形列表。在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 .应用场景

  1. 文件系统和目录结构表示
    • 描述层次关系:文件系统是典型的树形层次结构,由文件(叶子节点)和文件夹(组合节点)组成。组合模式可以很好地对其进行建模。例如,在操作系统的文件管理器中,每个文件夹可以包含文件和子文件夹,使用组合模式可以用统一的方式处理文件和文件夹的操作,如计算文件夹大小(需要递归计算子文件夹和文件的大小)、显示文件和文件夹列表、复制或移动文件夹(包括其内部的所有文件和子文件夹)等操作。
    • 权限管理:对于文件系统的访问权限设置,权限可以从文件夹继承到文件。通过组合模式,可以方便地为文件夹(组合节点)设置权限,并将这些权限传播给其包含的文件(叶子节点)和子文件夹,确保整个文件系统层次结构的权限一致性。
  2. 图形用户界面(GUI)组件层次结构
    • 构建界面布局:在GUI设计中,窗口、面板(如容器面板)是组合节点,而按钮、文本框等是叶子节点。组合模式用于构建复杂的用户界面布局。例如,一个窗口可以包含多个面板,每个面板又可以包含按钮、文本框等各种控件。通过组合模式,可以方便地添加、删除或重新排列这些界面组件,并且可以对整个界面或部分组件进行统一的操作,如显示、隐藏、设置样式等。
    • 事件处理和消息传递:在GUI系统中,事件(如鼠标点击、键盘输入)需要在组件层次结构中传播。组合模式可以帮助实现事件从顶层窗口向下传递到具体的叶子节点组件,或者从底层组件向上冒泡到父容器组件,从而实现合理的事件处理机制。
  3. 组织结构和资源管理
    • 企业组织结构建模:企业的组织结构是一个层次分明的体系,包括部门(组合节点)和员工(叶子节点)。组合模式可以用于表示这种组织结构,方便进行资源分配、任务分配等操作。例如,人力资源部门可以通过组合模式表示的组织结构,为整个公司(根节点)或者某个部门(子组合节点)统一进行工资核算、培训安排等操作,这些操作可以递归地应用到部门内的所有员工(叶子节点)。
    • 计算机集群资源管理:在计算机集群环境中,集群(组合节点)由多个计算节点(叶子节点)组成。通过组合模式,可以对集群资源进行统一管理,如分配任务到集群(将任务分配到具体的计算节点)、监控集群状态(包括各个计算节点的状态)、进行软件安装和更新(在集群范围内或者部分计算节点范围内)等操作。
  4. 游戏开发中的场景和对象管理
    • 游戏场景构建:游戏场景通常包含各种游戏对象,如角色(叶子节点)、道具(叶子节点)和地形(组合节点,可能包含多个子地形区域)等。组合模式可以用于构建游戏场景,方便游戏开发者添加、删除或修改游戏场景中的对象。例如,在一个角色扮演游戏中,可以通过组合模式创建一个包含多个区域(组合节点)的大地图场景,每个区域又包含角色、道具等对象,对整个场景或者部分区域的操作(如渲染、碰撞检测等)可以通过组合模式统一进行。
    • 游戏对象层次关系处理:游戏中的一些对象可能具有父子关系,如角色装备(叶子节点)与角色本身(组合节点)。通过组合模式,可以更好地处理这种对象层次关系,例如,当角色移动时,其装备也随之移动;当角色受到攻击时,其装备的属性(如防御值)可以对攻击进行响应,这种对象之间的关联和操作可以通过组合模式来清晰地实现。

相关文章:

重温设计模式--1、组合模式

文章目录 1 、组合模式&#xff08;Composite Pattern&#xff09;概述2. 组合模式的结构3. C 代码示例4. C示例代码25 .应用场景 1 、组合模式&#xff08;Composite Pattern&#xff09;概述 定义&#xff1a;组合模式是一种结构型设计模式&#xff0c;它允许你将对象组合成…...

单片机:实现SYN6288语音播报(附带源码)

单片机实现SYN6288语音播报 SYN6288是一款广泛应用于语音合成的IC&#xff0c;可以通过串口与单片机&#xff08;如51系列、STM32等&#xff09;进行通信&#xff0c;实现场景化的语音播报。通过连接外部存储设备&#xff08;如SD卡&#xff09;存储语音文件或直接通过内部语音…...

cookie,session,token 的区别

解决什么问题?Cookie&#xff08;客户端存储&#xff09;问题来了 Session&#xff08;会话&#xff09;解决的问题问题来了 token(令牌)解决的问题问题:token是无状态的如何解决? 解决什么问题? 解决http无状态的问题,说简单点就是用户身份的验证 举个例子: 张三在银行里…...

基于OpenAI Whisper AI模型自动生成视频字幕:全面解析与实战指南

在数字化时代&#xff0c;视频内容已成为信息传播的重要载体。然而&#xff0c;为视频添加字幕却是一项繁琐且耗时的工作。幸运的是&#xff0c;随着人工智能技术的飞速发展&#xff0c;特别是OpenAI Whisper模型的推出&#xff0c;我们有了更加高效、智能的解决方案。 一、Op…...

物理学天空的两朵乌云——量子论与相对论

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

聚类之轮廓系数

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

Jenkins 构建流水线

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

RTK部分模糊度固定测量流程图

部分模糊度剔除常用测量&#xff1a; 周跳或失锁时间优先剔除&#xff1b;按俯仰角剔除&#xff1b;按浮点模糊度协方差大小剔除模糊度&#xff1b;按信号强度剔除卫星&#xff1b;...

力扣-数据结构-2【算法学习day.73】

前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;建议灵神的题单和代码随想录&#xff09;和记录自己的学习过程&#xff0c;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关…...

操作系统导论读书笔记

目录 虚拟化抽象&#xff1a;进程抽象&#xff1a;进程概念 虚拟化 抽象&#xff1a;进程 本章讨论操作系统提供的基本的抽象—— 进程。进程的非正式定义非常简单&#xff1a;进程就是运行中的程序。程序本身是没有生命周期的&#xff0c;它只是存在磁盘上面的一些指令&…...

基于3D-Speaker进行区分说话人项目搭建过程报错记录 | 通话录音说话人区分以及语音识别 | 声纹识别以及语音识别 | pyannote-audio

0. 研究背景 在外呼系统中&#xff0c;我们的后台管理系统通常要对电话录音的内容进行提取和分析。那么说到分析&#xff0c;我们就要对录音中的两个人的对话进行分离&#xff0c;然后分别分析&#xff0c;比如分析客户是否有合作的意愿&#xff0c;分析客服讲的话术是否合理&…...

如何使用流式渲染技术提升用户体验

提示:记录工作中遇到的需求及解决办法 文章目录 什么是流式渲染?Node.js 实现简单流式渲染声明式 Shadow DOM,不依赖 javascript 实现react 实现流式渲染总结提示:以下是本篇文章正文内容,下面案例可供参考 什么是流式渲染? 流式渲染主要思想是将HTML文档分块(chunk)…...

【接口自动化连载】使用yaml配置文件自动生成接口case

直接上干货撸代码&#xff0c;有一些是通用的工具类代码&#xff0c;一次性封装永久使用&#xff0c;期待大家的关注&#xff0c;一起加油&#xff01;&#xff01;&#xff01; 配置文件 根据不同的业务需求进行配置&#xff0c;例如Goods服务、Order服务分开配置&#xff0…...

前端安全 常见的攻击类型及防御措施

1. 跨站脚本攻击&#xff08;XSS&#xff09; 描述&#xff1a;跨站脚本&#xff08;XSS&#xff1a;Cross-Site Scripting&#xff09;是一种安全漏洞&#xff0c;允许攻击者向网站注入恶意客户端代码。该代码由受害者执行从而让攻击者绕过访问控制并冒充用户。XSS攻击可以分…...

来道面试题——CopyOnWriteArrayList

原理 初始化时候&#xff0c;CopyOnWriteArrayList内部维护了一个可变数组&#xff0c;用于存储元素当执行数据变更操作的时候&#xff0c;会先创建一个原数组的副本&#xff0c;在副本上进行写操作&#xff0c;修改副本中的元素。写操作完成之后&#xff0c;把原数组的引用指…...

【Rust自学】5.1. 定义并实例化struct

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 5.1.1. 什么是struct struct的中文意思为结构体&#xff0c;它是一种自定义的数据类型&#xff0c;它允许程序为相关联的值命名和打包&am…...

React 生命周期完整指南

React 生命周期完整指南 1. 生命周期概述 1.1 React 16.3 之前的生命周期 初始化阶段 constructorcomponentWillMountrendercomponentDidMount 更新阶段 componentWillReceivePropsshouldComponentUpdatecomponentWillUpdaterendercomponentDidUpdate 卸载阶段 componentWil…...

python中os._exit(0) 强制关闭进程后来杀死线程

在 Python 中调用 os._exit(0) 会强制终止整个进程&#xff0c;包括所有正在运行的线程。以下是详细解释&#xff1a; os._exit(0) 的行为 立即终止进程&#xff1a;os._exit() 函数会立即终止当前进程&#xff0c;不会执行任何清理操作&#xff0c;如调用清理处理程序&#…...

LeetCode:257. 二叉树的所有路径

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

RSICV国产芯片之CHV208

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

all-MiniLM-L6-v2选型建议:何时选择轻量还是大模型

all-MiniLM-L6-v2选型建议&#xff1a;何时选择轻量还是大模型 all-MiniLM-L6-v2是一个轻量级的句子嵌入模型&#xff0c;基于BERT架构&#xff0c;专为高效语义表示设计。它采用6层Transformer结构&#xff0c;隐藏层维度为384&#xff0c;最大序列长度支持256个token&#x…...

Fader库:Arduino轻量级软件PWM LED渐变控制方案

1. Fader库概述&#xff1a;面向嵌入式LED调光的轻量级PWM渐变控制方案Fader是一个专为Arduino平台设计的轻量级LED亮度渐变控制库&#xff0c;其核心目标是提供一种资源占用极低、响应迅速且易于集成的软件PWM渐变方案。在资源受限的8位MCU&#xff08;如ATmega328P&#xff0…...

零成本上手:在魔塔社区用免费GPU微调InternLM2.5-7B-Chat实战

1. 为什么选择魔塔社区进行大模型微调 第一次接触大模型微调的朋友们可能都有这样的困惑&#xff1a;动辄几十GB的模型参数&#xff0c;没有高端显卡怎么玩得转&#xff1f;这里就要给大家安利一个宝藏平台——阿里魔塔社区。我去年刚开始研究大模型时&#xff0c;也是被硬件门…...

保姆级教程:用Zephyr RTOS 3.x和nRF52832开发板,5分钟跑通你的第一个BLE心率监测应用

从零构建基于Zephyr RTOS的BLE心率监测系统&#xff1a;nRF52832开发实战指南 在物联网和可穿戴设备爆发的时代&#xff0c;低功耗蓝牙&#xff08;BLE&#xff09;技术已成为连接智能设备的重要纽带。对于嵌入式开发者而言&#xff0c;掌握BLE开发意味着打开了通往智能硬件世界…...

Linux内存监控工具与实战技巧

1. Linux 内存监控概述作为一名运维工程师&#xff0c;我每天都要和服务器内存打交道。内存就像系统的血液&#xff0c;一旦出现异常&#xff0c;整个系统就会变得迟缓甚至崩溃。在Linux系统中&#xff0c;我们可以通过多种方式来监控内存使用情况&#xff0c;每种方法都有其独…...

GObject框架:C语言的面向对象编程实践

1. GObject框架概述GObject作为GLib库的核心组件&#xff0c;为C语言开发者提供了一套完整的面向对象编程范式。这个框架完美解决了C语言缺乏原生面向对象支持的痛点&#xff0c;让开发者能够在保持C语言高效性的同时&#xff0c;享受到面向对象编程的诸多优势。我在实际项目中…...

告别SBC音质焦虑!实测LC3编解码在TWS耳机上的音质与延迟表现(附对比数据)

告别SBC音质焦虑&#xff01;实测LC3编解码在TWS耳机上的音质与延迟表现&#xff08;附对比数据&#xff09; 作为一名长期被蓝牙音频压缩算法折磨的发烧友&#xff0c;第一次听到LC3编码的测试样机时&#xff0c;那种震撼感至今难忘——人声突然从蒙着纱布的状态变得触手可及&…...

专业的品牌策划企业

在竞争激烈的商业世界中&#xff0c;品牌是企业脱颖而出的关键。专业的品牌策划企业能够为企业量身定制品牌战略&#xff0c;助力企业在市场中占据一席之地。今天&#xff0c;我们就来深入了解一家在品牌策划领域颇具影响力的企业——湖南相传品牌设计有限公司&#xff0c;简称…...

Docker镜像推送到私有仓库完整指南:从命名规范到AWS ECR实战

镜像构建好了&#xff0c;放在本地只有自己能看见。团队其他人怎么用&#xff1f;部署服务器怎么拉&#xff1f;你需要一个私有镜像仓库。今天这篇文章&#xff0c;我们用AWS ECR&#xff08;Elastic Container Registry&#xff09;做例子&#xff0c;从创建仓库到推送镜像&am…...

深入解析MyBatis查询异常:org.apache.ibatis.exceptions.PersistenceException的排查与修复

1. 初识PersistenceException&#xff1a;MyBatis的"红色警报" 当你看到控制台突然抛出org.apache.ibatis.exceptions.PersistenceException时&#xff0c;就像开车时仪表盘突然亮起故障灯。这个异常是MyBatis框架的通用异常包装器&#xff0c;专门用来封装数据库操作…...