1.8 组合模式(Composite Pattern)
定义
组合模式(Composite Pattern) 是一种结构型设计模式,它将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式让客户端可以以相同的方式对待单个对象和对象集合。组合模式使得客户可以统一处理树形结构中的单个对象和对象的集合,简化了对象的使用和管理。
特性
- 树形结构:组合模式通过将多个对象组织成树形结构,使得客户可以通过一致的方式访问单个对象和对象集合。
- 统一接口:组合模式为所有对象提供一个共同的接口,让客户端以相同的方式处理叶子节点(单个对象)和组合节点(包含子对象的节点)。
- 递归结构:组合模式通常使用递归的方式来处理树形结构中的节点。
场景
适用场景
- 树形结构:当对象有部分-整体的层次关系时,组合模式可以提供统一的管理方式。例如,文件夹和文件的关系,组织结构的管理等。
- 需要统一处理叶子节点和组合节点的场景:当你需要统一处理单个对象和多个对象(集合)时,组合模式能够简化代码结构,避免大量的 if 或 switch 语句来分别处理单个对象和集合对象。
- UI组件结构:在构建图形用户界面(GUI)时,组件和容器通常呈现树形结构,可以使用组合模式来统一管理。
应用场景
- 文件系统:文件和文件夹之间具有“部分-整体”关系,文件夹中可以包含多个文件和子文件夹,组合模式可以帮助管理这一层次结构。
- UI组件:在GUI系统中,窗口、面板、按钮、标签等组件组成复杂的界面结构,组合模式能帮助统一管理这些组件。
- 组织结构:公司、部门、员工等可以构成树形结构,组合模式可以简化部门和员工的管理。
类设计
组合模式通常包括以下几个角色:
- Component(组件):定义叶子对象和组合对象的共同接口。它通常是一个抽象类或接口,声明了用于处理子对象的方法。
- Leaf(叶子节点):叶子对象没有子节点,表示组合中的基本元素,它实现了 Component 接口。
- Composite(组合节点):组合对象可以包含子对象(叶子节点或其他组合节点),它也实现了 Component 接口,并包含管理子对象的相关方法。
代码实现
我们以一个 组织结构(部门和员工)为例来演示组合模式。公司有多个部门,每个部门包含多个员工。部门本身也是一个对象,它可以包含其他部门(子部门)和员工(叶子节点)。
1. 定义组件接口(Component)
#include <iostream>
#include <vector>
#include <string>
using namespace std;// 组件接口:部门和员工的共同接口
class IComponent {
public:virtual void showInfo() = 0; // 显示信息virtual ~IComponent() {}
};
- IComponent 是所有部门和员工的公共接口,声明了 showInfo() 方法,用于展示信息。
2. 定义叶子节点类(Employee)
class Employee : public IComponent {
private:string name;string position;public:Employee(const string& name, const string& position) : name(name), position(position) {}void showInfo() override {cout << "Employee: " << name << ", Position: " << position << endl;}
};
- Employee 类代表组织结构中的叶子节点,即员工。
- 每个员工有姓名和职位,showInfo() 方法显示员工的基本信息。
3. 定义组合节点类(Department)
class Department : public IComponent {
private:string name;vector<IComponent*> children; // 子组件:可以是员工或子部门public:Department(const string& name) : name(name) {}void add(IComponent* component) {children.push_back(component); // 添加子部门或员工}void showInfo() override {cout << "Department: " << name << endl;for (IComponent* child : children) {child->showInfo(); // 遍历并显示子部门或员工信息}}
};
- Department 类是组合节点,可以包含员工(Employee)和子部门(Department)。
- add() 方法用于将员工或子部门添加到部门中。
- showInfo() 方法用于显示部门信息并递归调用子部门和员工的信息。
4. 客户端调用
int main() {// 创建员工IComponent* employee1 = new Employee("John Doe", "Software Engineer");IComponent* employee2 = new Employee("Jane Smith", "Product Manager");// 创建部门IComponent* department1 = new Department("Engineering");IComponent* department2 = new Department("Product");// 将员工添加到部门dynamic_cast<Department*>(department1)->add(employee1);dynamic_cast<Department*>(department2)->add(employee2);// 创建公司并添加部门Department* company = new Department("TechCorp");company->add(department1);company->add(department2);// 展示信息company->showInfo();// 清理内存delete employee1;delete employee2;delete department1;delete department2;delete company;return 0;
}
5. 输出结果
Department: TechCorp
Department: Engineering
Employee: John Doe, Position: Software Engineer
Department: Product
Employee: Jane Smith, Position: Product Manager
- 我们创建了一个 TechCorp 公司,它包含两个部门:“Engineering” 和 “Product”。
- 每个部门包含一个员工,Engineering 部门有一个软件工程师,Product 部门有一个产品经理。
- 最后,company->showInfo() 方法会递归地显示公司、部门和员工的完整信息。
组合模式的优缺点
优点:
- 简化客户端代码:客户端可以一致地处理单个对象和组合对象,无需关心它们的具体类型。
- 扩展性好:增加新的组合节点或叶子节点非常容易,只需要扩展 IComponent 接口和实现类。
- 透明化处理:组合模式隐藏了树形结构的复杂性,客户端不需要关心是操作叶子节点还是组合节点。
缺点:
- 管理复杂性:当树形结构很复杂时,组合模式可能会导致管理和维护复杂,尤其是当树的深度很大时。
- 效率问题:对于深度嵌套的树形结构,递归遍历可能会带来性能上的影响。
场景
适用场景:
树形结构:当系统中存在层次化的对象结构时,可以使用组合模式来组织这些对象。例如,文件系统、UI组件、组织结构等。
部分-整体结构:当需要对单个对象和对象集合进行一致的处理时,可以使用组合模式。
需要统一接口管理多层次结构:组合模式适合在管理层次结构时提供一个统一的接口。
编程案例
1.文件系统:在文件系统中,文件和文件夹之间存在“部分-整体”的层次结构。文件夹包含文件或子文件夹,文件夹本身也是一个对象,文件是叶子对象。通过组合模式,客户端可以通过统一接口操作文件和文件夹,而无需关心它们的具体类型。
2.UI组件的管理:在GUI设计中,窗口、面板、按钮等UI组件可以组成树形结构。窗口包含面板,面板包含按钮。使用组合模式,UI的管理和展示可以非常简洁,所有组件通过统一接口进行管理。
3.组织结构:公司和部门的组织结构是典型的“部分-整体”结构。部门下有员工、子部门等,组合模式可以将其简化为一个统一的接口来处理所有层级的对象。
总结
组合模式通过构建树形结构,允许客户端一致地处理单个对象和组合对象。它简化了树形结构的管理,使得对象的处理变得更加直观和方便。组合模式适用于有层次结构的场景,例如文件系统、组织结构、UI组件等,能够有效地将“部分-整体”结构统一化,减少了系统的复杂性和耦合度。
相关文章:
1.8 组合模式(Composite Pattern)
定义 组合模式(Composite Pattern) 是一种结构型设计模式,它将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式让客户端可以以相同的方式对待单个对象和对象集合。组合模式使得客户可以统一处理树形结构中的单个对象和对象的集合…...
QFileDialog::getOpenFileName(this,“文件对话框“,“.“,“c++ files(*.cpp);;“); 文件对话框显示乱码
在使用 QFileDialog::getOpenFileName 时,如果文件对话框显示乱码,通常是因为编码问题。Qt 默认使用 UTF-8 编码,但如果你的系统或源代码文件的编码不一致,可能会导致乱码。 以下是几种可能的解决方法: 1. 确保源代码…...
【C语言系列】深入理解指针(5)
深入理解指针(5) 一、sizeof和strlen的对比1.1sizeof1.2strlen1.3sizeof和strlen的对比 二、数组和指针笔试题解析2.1 一维数组2.2 字符数组2.2.1代码1:2.2.2代码2:2.2.3代码3:2.2.4代码4:2.2.5代码5&#…...
为什么使用nohup 和 启动的python脚本,日志没有在nohup.out中
当你使用 nohup 和 & 启动 Python 脚本时,输出通常会被重定向到 nohup.out 文件,但是有几个原因可能导致日志没有出现在这个文件中: Python 程序的输出被重定向了: 如果你的 Python 脚本中使用了 sys.stdout 或 sys.stderr 进…...
MySQL的存储引擎对比(InnoDB和MyISAM)
InnoDB 特点: 事务支持:InnoDB 是 MySQL 默认的事务型存储引擎,支持 ACID(原子性、一致性、隔离性、持久性)事务。行级锁定:支持行级锁,能够并发执行查询和更新操作,提升多用户环境…...
uniapp访问django目录中的图片和视频,2025[最新]中间件访问方式
新建中间件, middleware.py 匹配,以/cover_image/ 开头的图片 匹配以/episode_video/ 开头的视频 imageSrc: http://192.168.110.148:8000/cover_image/12345/1738760890657_mmexport1738154397386.jpg, videoSrc: http://192.168.110.148:8000/episode_video/12345/compres…...
Python递归复习题
寒假打卡第二十一天,当前mit6.100L进度(16/26) ,今天补一下递归复习题。 问题1:编写一个递归程序来计算正和n(n-2)(n-4)的整数(直到且不包括n-x<0) def sum_series(n…...
2025 年前端开发趋势展望,开启新征程
新年伊始,作为一名深耕 Web 前端开发领域的博主,我迫不及待地想和大家分享我对 2025 年前端开发趋势的洞察。过去一年里,前端领域的技术创新和变革令人目不暇接,而新的一年,更是充满无限可能。 框架与工具的持续演进 …...
90,【6】攻防世界 WEB Web_php_unserialize
进入靶场 进入靶场 <?php // 定义一个名为 Demo 的类 class Demo { // 定义一个私有属性 $file,默认值为 index.phpprivate $file index.php;// 构造函数,当创建类的实例时会自动调用// 接收一个参数 $file,用于初始化对象的 $file 属…...
Redis --- 使用GEO实现经纬度距离计算
什么是GEO? Spring Boot 项目中可以通过 Spring Data Redis 来使用 Redis GEO 功能,主要通过 RedisTemplate 和 GeoOperations 接口来操作地理位置数据。 Service public class GeoService {Autowiredprivate RedisTemplate<String, Object> red…...
同步 CDC
同步 CDC 当设计包括来自同一 MMCM/PLL 的时钟之间的同步 CDC 路径时,您可以使用以下技术来更好地控制时钟插入延迟和 时滞,并因此控制这些路径上的松弛。 重要提示: 如果 CDC 路径在源自不同 MMCM/PLL 的时钟之间,则跨越 …...
Linux环境下载Ollama慢或卡顿解决方案
一、下载方式 官方下载方式是到ollama官网下载ollama: https://ollama.com/ 复制下载链接执行: curl -fsSL https://ollama.com/install.sh | sh二、卡顿现象 执行后经常会出现下载失败或者进度条特别慢的情况,甚至直接退出下载: 三、…...
生成式AI安全最佳实践 - 抵御OWASP Top 10攻击 (下)
今天小李哥将开启全新的技术分享系列,为大家介绍生成式AI的安全解决方案设计方法和最佳实践。近年来生成式 AI 安全市场正迅速发展。据IDC预测,到2025年全球 AI 安全解决方案市场规模将突破200亿美元,年复合增长率超过30%,而Gartn…...
2025年家用音响市场分析:潜力无限,音质为王的新纪元
引言:音质革命引领市场新风尚 在数字化浪潮的推动下,家用音响市场正经历一场前所未有的变革,其增长潜力犹如破晓之光,照亮了音频技术的未来之路。随着消费者对高品质生活追求的不断提升,以及对智能家居生态融合的日益…...
neo4j-在Linux中安装neo4j
目录 切换jdk 安装neo4j 配置neo4j以便其他电脑可以访问 切换jdk 因为我安装的jdk是1.8版本的,而我安装的neo4j版本为5.15,Neo4j Community 5.15.0 不支持 Java 1.8,它要求 Java 17 或更高版本。 所以我需要升级Java到17 安装 OpenJDK 17 sudo yu…...
AI 场景下,函数计算 GPU 实例模型存储最佳实践
作者:有松 当前,函数计算 FC 已被广泛应用在各种 AI 场景下,函数计算支持通过使用容器镜像部署 AI 推理应用,并且提供多种选项来访问训练好的模型。为了帮助开发者高效地在函数计算上部署 AI 推理应用,并快速解决不同…...
股指入门:股指期货是什么意思?在哪里可以做股指期货交易?
股指期货是一种以股票指数为标的物的期货合约,也可以称为股票指数期货或期指。 股指期货是什么意思? 股指期货是一种金融衍生品,其标的资产是股票市场上的股指,例如标普500指数、道琼斯工业平均指数、上证50指数等。 股指期货允…...
【分布式理论六】分布式调用(4):服务间的远程调用(RPC)
文章目录 一、RPC 调用过程二、RPC 动态代理:屏蔽远程通讯细节1. 动态代理示例2. 如何将动态代理应用于 RPC 三、RPC 序列化四、RPC 协议编码1. 协议编码的作用2. RPC 协议消息组成 五、RPC 网络传输1. 网络传输流程2. 关键优化点 一、RPC 调用过程 RPC(…...
aliyun 的 ip 设置方法
aliyun 的 ip 设置方法 阿里云:网络编程 bind:cannot assign requested address errno:99 问题。 公网IP,,弹性公网IP,主私网IP 1. 公网IP, --> NAT --> 主私网IP ,设置方法: 服务器端 ip 为&…...
ASP.NET Core分布式缓存
目录 分布式缓存 概述 IDistributedCache接口中定义的主要方法及主要的扩展方法 用什么做缓存服务器 使用 封装分布式缓存操作 分布式缓存 概述 分布式系统中,内存缓存不满足要求的话,把缓存数据保存到专门的缓存服务器,所有Web应用通…...
【CUDA】内存模型
目录 一、Programmable 1.1 寄存器(Registers) 1.2 本地内存(Local Memory) 1.3 共享内存(shared Memory) 1.4 常量内存(Constant Memory) 1.5 全局内存(Global Memory) 1.6 纹理内存(Textrue Memory) 1.7 总结 二、Cache(Non-programmable) 三、固定内存 四、零拷贝…...
使用Pygame制作“吃豆人”游戏
本篇博客展示如何使用 Python Pygame 编写一个简易版的“吃豆人(Pac-Man)” 风格游戏。这里我们暂且命名为 Py-Man。玩家需要控制主角在一个网格地图里移动、吃掉散布在各处的豆子,并躲避在地图中巡逻的幽灵。此示例可帮助你理解网格地图、角…...
Pyecharts系列课程04——折线图/面积图(Line)
本章我们学习在Pyecharts中折线图(Line)的使用。折线图通用应用于数据的趋势分析。 折线图 我们现在有两组数据,x_data是2024年的月份,y_data为对应张三甲每个月的用电量。 # 家庭每月用电量趋势 x_data ["1月", &q…...
mysql 学习10 多表查询 -多表关系,多表查询
多表关系 一对多 多对多 创建学生表 #多对多表 学生选课系统create table student(id int primary key auto_increment comment 主键ID,name varchar(64) comment 姓名,studentnumber varchar(10) comment 学号 )comment 学生表;insert into student(id,name,studentnumber)va…...
lambda 表达式详解
lambda 表达式详解 lambda 表达式详解基本语法示例代码及详细解释1. 简单的lambda表达式2. 带参数的lambda表达式3. 捕获外部变量4. 使用mutable关键字修改捕获的变量5. 按引用捕获外部变量6. 自动推导返回类型 捕获列表的几种形式总结 Lambda表达式的常用的应用场景࿱…...
从0开始达芬奇(3.5)
媒体优化 顾名思义就是降低分辨率等来使素材的回放更加流畅。(在低配电脑上也可以流畅运行) ⭐方法一:(一般使用第二种) 播放→代理模式→二分之一或者四分之一 ⭐⭐⭐方法二:优化媒体文件(简…...
【Uniapp-Vue3】z-paging插件组件实现触底和下拉加载数据
一、下载z-paing插件 注意下载下载量最多的这个 进入Hbuilder以后点击“确定” 插件的官方文档地址: https://z-paging.zxlee.cn 二、z-paging插件的使用 在文档中向下滑动,会有使用方法。 使用z-paging标签将所有的内容包起来 配置标签中的属性 在s…...
Ubuntu20.04 本地部署 DeepSeek-R1
一、下载ollama 打开 ollama链接,直接终端运行提供的命令即可。如获取的命令如下: curl -fsSL https://ollama.com/install.sh | sh确保是否安装成功可在终端输入如下命令: ollama -v注意: 如遇到Failed to connect to github.…...
Linux 设备驱动分类(快速理解驱动架构)
Linux 设备驱动分类(快速理解驱动架构) 在 Linux 设备驱动开发中,最基础的概念就是 设备驱动的分类。 Linux 设备驱动主要分为 字符设备、块设备和网络设备,它们分别对应不同类型的硬件资源。 理解这些分类,不仅能帮助…...
Java语法糖详解
前言 在现代编程语言的发展历程中,语法糖(Syntactic Sugar)作为一种提升代码可读性和开发效率的重要特性,已经成为语言设计的重要组成部分。Java作为一门成熟且广泛应用的编程语言,在其长期演进过程中,语法…...
567.字符串的排列
目录 一、题目二、思路2.1 解题思路2.2 代码尝试2.3 疑难问题 三、解法四、收获4.1 心得4.2 举一反三 一、题目 二、思路 2.1 解题思路 用两个哈希表比较来判断。s1的哈希表是否与s2相同。在窗口滑动过程中,用哈希表来维护。 2.2 代码尝试 class Solution { pub…...
DB2和mysql关于表和索引是否需要reorg的研究
DB2: DB2有个reorgchk的命令,是从SYSSTAT.TABLES和syscat.indexes这两个系统表中查表和索引的信息,并给出是否需要reorg表和索引的建议。 [db2inst1t3-ucm-ucm-rdb ~]$ db2 reorgchk CURRENT STATISTICS on table DB2ADMIN.ACAGENTTREE Ta…...
【Linux系统编程】:自旋锁,读写锁
文章目录 前言1. POSIX自旋锁1.1.定义自旋锁1.2.初始化1.3. 加锁1.4. 尝试加锁操作1.5. 解锁操作1.6. 销毁操作1.7.示例1.8.优缺点优点缺点 1.9.适用场景 2. 读写锁2.1 读写锁的工作原理2.2 读写模型2.3 常用接口2.3.1 定义锁并初始化2.3.2 申请读锁2.3.3 申请写锁2.3.4 解锁2.…...
位运算及常用技巧
涉及位运算的运算符如下表所示: 位运算的运算律: 负数的位运算 首先,我们要知道,在计算机中,运算是使用的二进制补码,而正数的补码是它本身,负数的补码则是符号位不变,其余按位取反…...
Chrome 浏览器:互联网时代的浏览利器
Chrome 浏览器:互联网时代的浏览利器 引言 在互联网时代,浏览器已经成为我们日常生活中不可或缺的工具。作为全球最受欢迎的浏览器之一,Chrome 浏览器凭借其出色的性能、丰富的扩展程序和简洁的界面,赢得了广大用户的喜爱。本文…...
web-文件上传-CTFHub
前言 在众多的CTF平台当中,作者认为CTFHub对于初学者来说,是入门平台的不二之选。CTFHub通过自己独特的技能树模块,可以帮助初学者来快速入门。具体请看官方介绍:CTFHub。 作者更新了CTFHub系列,希望小伙伴们多多支持…...
【react】react面试题
react面试题 对 React 的理解、特性 react18有哪些更新 JSX是什么 解释为什么浏览器不能读取jsx ReactNative中,如何解决8081端口被占用而提示无法访问的问题? React 生命周期 react事件机制 react 组件传值 React改变state的方式 re…...
逐笔成交逐笔委托Level2高频数据下载和分析:20250206
Level2逐笔成交逐笔委托数据分享下载 通过Level2逐笔成交和逐笔委托这种每一笔的毫秒级别的数据可以分析出很多有用的点,包括主力意图,虚假动作,让任何操作无所遁形。适合交易大师来分析主力规律,也适合人工智能领域的机器学习&a…...
__cvta_generic_to_shared
一 测试代码 #include <cuda_runtime.h> #include <cstdio> #include <cstdint>__global__ void test_cp_async(int* __restrict__ A,int* __restrict__ B){int tid = threadIdx.x;A[tid] = tid;__shared__ int smem[32];size_t smemAddr = __cvta_generic_…...
C++学习——缺省参数、重载函数、引用
目录 前言 一、缺省参数 1.1概念 1.2写法 1.3半缺省 1.4使用 二、重载函数 2.1.概念 2.2类型 2.3参数 2.4顺序 2.5问题 2.6原理 三、引用 1、引用是什么? 2、引用的使用方法 3、引用特性 1、引用在定义的时候必须要初始化 2、一个变量会有多个引用…...
docker-compose 配置nginx
前言 前端打包的dist文件在宿主机,nginx运行在docker-compose 问题 nginx.conf 在本地配置可以生效,但是链接到容器就报错 基于本地的nginx运行,本地nginx.conf 如下 server {listen 8081;location / {root /usr/local/software/testweb/…...
LQB(0)-python-基础知识
一、Python开发环境与基础知识 python解释器:用于解释python代码 方式: 1.直接安装python解释器 2.安装Anaconda管理python环境 python开发环境:用于编写python代码 1.vscode 2.pycharm # 3.安装Anaconda后可以使用网页版的jupyter n…...
【C语言】指针运算与数组关系:详细分析与实例讲解
博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C语言 文章目录 💯前言💯1. 指针的基础运算1.1 指针的加减运算1.2 指针加整数与指针减整数1.3 指针与指针的运算 💯2. 指针的实际应用:模拟 strlen 函数2.1 使用指针模拟…...
C++数组
指针,是C数组工作方式的基础。 数组,基本上是元素的集合。按特定的顺序排列的一堆东西。 C数组,就是表示一堆的变量组成的集合。一般是一行相同类型的变量。 例子: #include <iostream> int main() {int example[5];exa…...
OSPF基础(2)
一、LSA的头部 LSA是OSPF的一个核心内容,如果没有LSA,OSPF是无法描述网络的拓扑结构及网段信息的,也无法传递路由信息,更加无法正常工作,在OSPFV2中,需要我们掌握的主要有6种。 LSA头部一共20byte,每个字段…...
DeepSeek R1 简单指南:架构、训练、本地部署和硬件要求
DeepSeek 的 LLM 推理新方法 DeepSeek 推出了一种创新方法,通过强化学习 (RL) 来提高大型语言模型 (LLM) 的推理能力,其最新论文 DeepSeek-R1 对此进行了详细介绍。这项研究代表了我们如何通过纯强化学习来增强 LLM 解决复杂问题的能力,而无…...
javaEE-6.网络原理-http
目录 什么是http? http的工作原理: 抓包工具 fiddler的使用 HTTP请求数据: 1.首行:编辑 2.请求头(header) 3.空行: 4.正文(body) HTTP响应数据 1.首行:编辑 2.响应头 3.空行: 4.响应正文…...
把bootstrap5.3.3整合到wordpress主题中的方法
以下是将 Bootstrap 5.3.3 整合到 WordPress 主题中的方法: 下载 Bootstrap 文件:从 Bootstrap 官网下载最新的 5.3.3 版本的 CSS 和 JavaScript 文件。 上传文件到主题目录:将下载的 CSS 文件上传到 WordPress 主题文件夹中的 /css 文件夹…...
深度整理总结MySQL——Buffer Pool工作原理
Buffer Pool工作原理 前言为什么会有Buffer PoolBuffer Pool介绍Buffer Pool有多大Buffer Pool缓存什么呢Buffer Pool碎片空间查询一条记录,就只需要缓冲一条记录吗 如何管理Buffer Pool如何管理空闲页如何管理脏页如何提高缓存命中率 LRU带来的问题预读失效Buffer …...
langchain教程-9.Retriever/检索器
前言 该系列教程的代码: https://github.com/shar-pen/Langchain-MiniTutorial 我主要参考 langchain 官方教程, 有选择性的记录了一下学习内容 这是教程清单 1.初试langchain2.prompt3.OutputParser/输出解析4.model/vllm模型部署和langchain调用5.DocumentLoader/多种文档…...