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

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

文章目录

  • 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. 游戏开发中的场景和对象管理
    • 游戏场景构建:游戏场景通常包含各种游戏对象,如角色(叶子节点)、道具(叶子节点)和地形(组合节点,可能包含多个子地形区域)等。组合模式可以用于构建游戏场景,方便游戏开发者添加、删除或修改游戏场景中的对象。例如,在一个角色扮演游戏中,可以通过组合模式创建一个包含多个区域(组合节点)的大地图场景,每个区域又包含角色、道具等对象,对整个场景或者部分区域的操作(如渲染、碰撞检测等)可以通过组合模式统一进行。
    • 游戏对象层次关系处理:游戏中的一些对象可能具有父子关系,如角色装备(叶子节点)与角色本身(组合节点)。通过组合模式,可以更好地处理这种对象层次关系,例如,当角色移动时,其装备也随之移动;当角色受到攻击时,其装备的属性(如防御值)可以对攻击进行响应,这种对象之间的关联和操作可以通过组合模式来清晰地实现。

相关文章:

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

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

5、mysql的读写分离

主从复制 主从复制的含义 主从复制&#xff1a;在一个mysql的集群当中&#xff0c;至少3台&#xff0c;即主1台&#xff0c;从2台。 当有数据写入时&#xff0c;主负责写入本库&#xff0c;然后把数据同步到从服务器。 一定是在主服务器写入数据&#xff0c;从服务器的写入…...

uniapp Native.js原生arr插件服务发送广播到uniapp页面中

前言 最近搞了个设备&#xff0c;需求是读取m1卡&#xff0c;厂家给了个安卓原生demo&#xff0c;接入arr插件如下&#xff0c;接入后发现还是少了一部分代码&#xff0c;设备服务调起后触发刷卡无法发送到uniapp里。 中间是一些踩坑记录&#xff0c;最后面是解决办法&#xf…...

如何在 Ubuntu 22.04 上安装 Elasticsearch

简介 在本教程中&#xff0c;你将学习如何在 Ubuntu 22.04 服务器上安装 Elasticsearch。此外&#xff0c;你还将学习如何使用 Elasticsearch REST API 索引和操作数据。 Elasticsearch 是一个基于 Apache Lucene Library 的免费分布式搜索和分析引擎。它是一个快速且可扩展的…...

单片机长耗时前后台任务优化

代码&#xff1a; void Task_10ms(void) {... }//改 void Task_2ms(void) {static uint8_t s_state 0switch(s_state){case 0:....s_state 1;break;case 1:....s_state 2;break;case 3:....s_state 1;break;default: //此段可以去除s_state 0;break; } } 参考链接 MCU长…...

Linux大数据方向shell

一、概述 shell是一个命令行解释器&#xff0c;它接收应用程序/用户命令&#xff0c;然后调用操作系统内核&#xff0c;还是一个功能相当强大的编程语言&#xff0c;易编写&#xff0c;易调试&#xff0c;灵活性强。 二、shell入门 1.输出hello world touch helloworld.sh&…...

爬虫 APP 逆向 ---> shopee(虾皮) 电商

shopee 泰国站点&#xff1a;https://shopee.co.th/ shopee 网页访问时&#xff0c;直接弹出使用 app 登录查看&#xff0c;那就登录 shopee 泰国站点 app。 手机抓包&#xff1a;分类接口 接口&#xff1a;https://mall.shopee.co.th/api/v4/pages/get_category_tree 请求参…...

axios 常见的content-type、responseType有哪些?

一、Content Type Content Type &#xff0c;也被称为MIME类型&#xff08;Multipurpose Internet Mail Extensions&#xff09;&#xff0c;是一种用于标识数据格式的机制。在HTTP协议中&#xff0c;Content Type’通常通过请求或响应头部的’Content-Type’字段来指定。这个…...

从零开始C++游戏开发之第七篇:游戏状态机与回合管理

在游戏开发的道路上&#xff0c;状态管理是一个无法绕开的重要课题。尤其是在棋牌类游戏中&#xff0c;游戏的进行需要有条不紊地按照回合推进&#xff0c;同时管理多个游戏状态&#xff0c;如“等待玩家加入”、“游戏进行中”、“结算阶段”等。如何优雅且高效地实现这些逻辑…...

【全开源】Java多语言tiktok跨境商城TikTok内嵌商城送搭建教程

开发工具&#xff1a;IntelliJ IDEA 部署环境: Tomcat8.x Mysql5.6 JDK1.8 Maven3.x Redis ZooKeeper3.4。 本系统开发使用JAVA技术栈开发 使用uniapp技术栈 支持多端 H5AndroidIOS PC端使用&#xff1a;vueelementui 用户端使用&#xff1a;uniapp 管理端使用&#xff1a…...

mac启ssh服务用于快速文件传输

x.1 在mac上启SSH服务 方法一&#xff1a;图形交互界面启ssh&#xff08;推荐&#xff09; 通过sharing - advanced - remote login来启动ssh&#xff1b;&#xff08;中文版mac应该是 “系统设置 → 通用 → 共享”里打开“远程登录”来启动&#xff09; 查看自己的用户名和…...

《探索 Apache Spark MLlib 与 Java 结合的卓越之道》

在当今大数据与人工智能蓬勃发展的时代&#xff0c;Apache Spark MLlib 作为强大的机器学习库&#xff0c;与广泛应用的 Java 语言相结合&#xff0c;为数据科学家和开发者们提供了丰富的可能性。那么&#xff0c;Apache Spark MLlib 与 Java 结合的最佳实践究竟是什么呢&#…...

使用 Python 创建多栏 Word 文档 – 详解

目录 引言 一、工具与安装 二、Python 在 Word 中创建简单的多栏布局 三、Python 在 Word 文档的栏间添加分隔线 四、Python 从Word文档的指定位置开启多栏设置 五、Python 为多栏 Word 文档的各栏添加页码 引言 在文档设计中&#xff0c;排版不仅决定了内容的呈现方式&…...

WebPack3项目升级webpack5的配置调试记录

文章目录 前言一、webpack3环境1.1、知识点记录1.1.1、配置解释1.1.2、webpack与sass版本对应关系1.1.3、CommonJS与ESModule1.1.4、node版本管理nvm1.1.5、sass-loader、sass与node-sass 1.2、其他1.2.1、.d.ts是什么文件1.2.2、react与types/react版本对应关系1.2.3、webpack…...

Mysql的MHA高可用及故障切换

Mysql的MHA高可用及故障切换 MHA主从复制的单点问题配置1. 主从复制2. MHA高可用安装MHA的组件配置无密码认证manager节点配置manager节点上测试启动连接 故障切换模拟恢复 MHA master high availability 建立在主从复制基础之上的故障切换的软件系统。 主从复制的单点问题 …...

【ES6复习笔记】箭头函数(5)

简介 本教程将介绍如何在 JavaScript 中使用箭头函数&#xff0c;包括箭头函数的基本语法、特点以及在实际开发中的应用。通过本教程&#xff0c;你将学会如何使用箭头函数来简化代码&#xff0c;提高代码的可读性和简洁性。 箭头函数的基本语法 箭头函数是 ES6 引入的一种新…...

单片机学习笔记——入门51单片机

一、单片机基础介绍 1.何为单片机 单片机&#xff0c;英文Micro Controller Unit&#xff0c;简称MCU 。内部集成了中央处理器CPU、随机存储器ROM、只读存储器RAM、定时器/计算器、中断系统和IO口等一系列电脑的常用硬件功能 单片机的任务是信息采集&#xff08;依靠传感器&a…...

Docker Run使用方法及参数详细说明

Docker Run使用方法及参数详细说明 基本语法常用参数使用示例总结Docker Run是Docker中最基本的命令之一,用于创建并启动一个新的容器。通过Docker Run,用户可以基于指定的镜像创建一个容器实例,并且可以配置容器的各种参数,如网络设置、存储选项等。下面将详细介绍Docker …...

面试场景题系列:设计限流器

首先看看使用API限流器的好处。 •预防由拒绝服务攻击(Denial of Service&#xff0c;DoS)引起的资源耗尽问题。大型科技公司发布的所有API几乎都强制执行某种形式的限流操作。例如&#xff0c;推特限制每个用户每3小时最多发300条推文。谷歌文档API的默认限制是每个用户每60秒…...

【蓝桥杯——物联网设计与开发】拓展模块3 - 温度传感器模块

目录 一、温度传感器模块 &#xff08;1&#xff09;资源介绍 &#x1f505;原理图 &#x1f505;STS30-DIS-B &#x1f319;引脚分配 &#x1f319;通信 &#x1f319;时钟拉伸&#xff08;Clock Stretching&#xff09; &#x1f319;单次触发模式 &#x1f319;温度数据转…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

可靠性+灵活性:电力载波技术在楼宇自控中的核心价值

可靠性灵活性&#xff1a;电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中&#xff0c;电力载波技术&#xff08;PLC&#xff09;凭借其独特的优势&#xff0c;正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据&#xff0c;无需额外布…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

GC1808高性能24位立体声音频ADC芯片解析

1. 芯片概述 GC1808是一款24位立体声音频模数转换器&#xff08;ADC&#xff09;&#xff0c;支持8kHz~96kHz采样率&#xff0c;集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器&#xff0c;适用于高保真音频采集场景。 2. 核心特性 高精度&#xff1a;24位分辨率&#xff0c…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

论文笔记——相干体技术在裂缝预测中的应用研究

目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术&#xff1a;基于互相关的相干体技术&#xff08;Correlation&#xff09;第二代相干体技术&#xff1a;基于相似的相干体技术&#xff08;Semblance&#xff09;基于多道相似的相干体…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解

进来是需要留言的&#xff0c;先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码&#xff0c;输入的<>当成字符串处理回显到页面中&#xff0c;看来只是把用户输…...

6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础

第三周 Day 3 &#x1f3af; 今日目标 理解类&#xff08;class&#xff09;和对象&#xff08;object&#xff09;的关系学会定义类的属性、方法和构造函数&#xff08;init&#xff09;掌握对象的创建与使用初识封装、继承和多态的基本概念&#xff08;预告&#xff09; &a…...

《信号与系统》第 6 章 信号与系统的时域和频域特性

目录 6.0 引言 6.1 傅里叶变换的模和相位表示 6.2 线性时不变系统频率响应的模和相位表示 6.2.1 线性与非线性相位 6.2.2 群时延 6.2.3 对数模和相位图 6.3 理想频率选择性滤波器的时域特性 6.4 非理想滤波器的时域和频域特性讨论 6.5 一阶与二阶连续时间系统 6.5.1 …...