组合模式(Composite)
组合模式是一种结构型设计模式,主要用来将多个对象组织成树形结构以表示“部分-整体”的层次结构,因此该模式也称为“部分-整体”模式。简言之,组合模式就是用来将一组对象组合成树状结构,并且能像使用独立对象一样使用它们。
Composite is a structural design pattern that lets you organize multiple objects into a tree structure to represent the "part whole" relationship. In short, the composite pattern can be used to combine a group of objects into a tree structure and use them as independent objects.
结构设计
为实现组合模式,首先需要创建一个可以组合多个对象的单一对象(Component),这个对象用来访问和管理其子对象,并对外提供公共接口。然后,定义没有子节点的对象(Leaf,基本对象)和包含子对象的对象(Composite,组合对象)。最后,将这些对象组装到之前创建的对象上。这样,外部(Client)就可通过Component调用公共接口。组合模式包含如下角色:
Component,组合对象,为组合中的对象声明公共接口,并提供默认实现。
Leaf,叶节点对象,叶节点最终会完成大部分的实际工作,因为它们无法将工作指派给其他部分。
Compoiste,组合,也称容器,包含叶节点或其他容器的单位。容器不知道其子项目所属的具体类, 它只通过通用的组件接口与其子项目交互。
组合模式类图表示如下:

注意:
(1) 组合模式对基本对象和组合对象的使用具有一致性。外部代码调用Component公共接口时,无需区别对待基本对象和组合对象(透明性),大多数情况下可以一致地处理它们。
伪代码实现
接下来将使用代码介绍下组合模式的实现。
// 1、Component,组合对象,为组合中的对象声明公共接口,并提供默认实现。
public abstract class Component {private String name;protected List<Component> children = new ArrayList<>();public Component(String componentName) {this.name = componentName;}public void operation() {System.out.println(this.name);}public Component getChild(String componentName) {for (Component current : children) {if (current.name.equals(componentName)) {return current;}Component childComponent = current.getChild(componentName);if (childComponent != null) {return childComponent;}}return null;}public abstract void add(Component component);public abstract void remove(Component component);
}
// 2、Compoiste,组合,也称容器,包含叶节点或其他容器的单位。容器不知道其子项目所属的具体类,
// 它只通过通用的组件接口与其子项目交互。
public class Composite extends Component {public Composite(String componentName) {super(componentName);}@Overridepublic void add(Component component) {this.children.add(component);}@Overridepublic void remove(Component component) {this.children.remove(component);}
}
// 3、Leaf,叶节点对象,叶节点最终会完成大部分的实际工作,因为它们无法将工作指派给其他部分。
public class Leaf extends Component {public Leaf(String componentName) {super(componentName);}@Overridepublic void add(Component component) {throw new RuntimeException("叶节点不能添加子节点");}@Overridepublic void remove(Component component) {throw new RuntimeException("叶节点不包含子节点,无法移除子节点");}
}
// 4、客户端调用
public class CompositeClient {public void test() {Component root = new Composite("root");root.add(new Leaf("Leaf A"));Composite branch = new Composite("Composite X");Leaf leafXa = new Leaf("Leaf XA");branch.add(leafXa);branch.add(new Leaf("Leaf XB"));branch.remove(leafXa);root.add(branch);Component leafXb = root.getChild("Leaf XB");leafXb.operation();}
}
这里只介绍了基于透明性的设计与实现,组合模式还支持一种基于安全性的设计与实现,更多安全性相关知识可以执行搜索并学习。
适用场景
在以下情况下可以考虑使用组合模式:
(1) 如果需要实现树状对象结构, 可以考虑使用组合模式。
组合模式提供了两种共享公共接口的基本元素类型:简单叶节点和复杂容器。容器中可以包含叶节点和其他容器。这使得开发者可以构建树状嵌套递归对象结构。
(2) 如果希望客户端代码以相同方式处理简单和复杂元素, 可以使用该模式。
组合模式中定义的所有元素共用同一个接口。在这一接口的帮助下,客户端不必在意其所使用的对象的具体类。
优缺点
组合模式最大特点是将多个对象组织成树形结构。组合模式有以下优点:
(1) 可以利用多态和递归机制更方便地使用复杂树结构。
(2) 符合开闭原则。无需更改现有代码,开发者就可以在应用中添加新元素,使其成为对象树的一部分。
但是组合模式也存在以下缺点:
(1) 对于功能差异较大的类, 提供公共接口或许会有困难。在特定情况下,开发者需要过度一般化组件接口,使其变得令人难以理解。
参考
《设计模式:可复用面向对象软件的基础》 Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides 著 李英军, 马晓星 等译
https://refactoringguru.cn/design-patterns/composite 组合模式
https://www.cnblogs.com/adamjwh/p/9033547.html 简说设计模式——组合模式
https://blog.csdn.net/ShuSheng0007/article/details/116378002 秒懂设计模式之组合模式(Composite Pattern)
https://www.runoob.com/design-pattern/composite-pattern.html 组合模式
相关文章:
组合模式(Composite)
组合模式是一种结构型设计模式,主要用来将多个对象组织成树形结构以表示“部分-整体”的层次结构,因此该模式也称为“部分-整体”模式。简言之,组合模式就是用来将一组对象组合成树状结构,并且能像使用独立对象一样使用它们。 Co…...
grid map学习笔记3之详解grid_map_pcl库实现point cloud点云转换成grid map栅格地图
文章目录 0 引言1 grid_map_pcl示例1.1 主要文件1.2 示例数据1.3 启动文件1.4 配置文件1.5 主要实现流程1.6 启动示例1.7 示例结果 2 D435i 点云生成栅格地图2.1 D435i 点云文件2.2 修改启动文件2.3 测试和结果2.4 修改配置文件2.5 重新测试和结果 0 引言 grid map学习笔记1已…...
ebpf开发问题汇总
不同Programs之间通信 用bpf_obj_get来获取MAP的描述符,然后用bpf_map_reuse_fd函数来在不同program之间复用 kernel 与 user space之间 需要pin the BPF MAP to the BPF Virtual File System (VFS),来持久化存储,否则如果map用不到会被destory 引用…...
认识 mysql 命令
文章目录 1.简介2.选项3.子命令4.小结参考文献 1.简介 mysql 是 MySQL 的命令行客户端工具,用于连接到 MySQL 服务器并执行 SQL 语句。 它支持交互式和非交互式两种使用方式。以交互方式使用时,查询结果以 ASCII 表格式呈现。 当以非交互方式使用时&am…...
IK(Inverse Kinematics,逆运动学)
介绍 在Unity中,IK(Inverse Kinematics,逆运动学)是一种用于控制角色或物体骨骼的技术。通过使用IK,可以实现更自然和真实的动画效果,特别是在处理复杂的角色动作时非常有用。 IK Pass是Unity中的一个功能…...
Cadence 小技巧系列(持续更新)
■ ADE setup simulator/directory/host 更改仿真路径,默认home路径空间太小了,改成当前路径就行。 瞬态tran仿真要用APS跑(setup--high...) 瞬态tran仿真精度设置,conservation,option--maxstep设为0.1n…...
【unity】Pico VR 开发笔记(基础篇)
Pico VR 开发笔记(基础篇) XR Interaction Tooikit 版本 2.3.2 一、环境搭建 其实官方文档已经写的很详细了,这里只是不废话快速搭建,另外有一项官方说明有误的,补充说明一下,在开发工具部分说明 插件安装——安装pico的sdk和XR…...
竞争之王CEO商战课,聚百家企业在京举行
竞争之王CEO商战课,于2023年7月29-31日在北京临空皇冠假日酒店举办,近百家位企业家齐聚一堂,共享饕餮盛宴。 竞争之王CEO商战课是打赢商战的第一课。 竞争环境不是匀速变化,而是加速变化。 在未来的市场环境中,企业间…...
【shell】获取ping的时延数据并分析网络情况及常用命令学习
文章目录 获取ping的时延数据并分析网络情况|、||、&、&&辨析teetailkillall 获取ping的时延数据并分析网络情况 网络情况经常让我们头疼,每次都需要手动在终端ping太麻烦了,不如写个脚本ping并将数据带上时间戳存入文件,然后也…...
石子合并一章通(环形石子合并,四边形不等式,GarsiaWachs算法)(内附封面)
[NOI1995] 石子合并 题目描述 在一个圆形操场的四周摆放 N N N 堆石子,现要将石子有次序地合并成一堆,规定每次只能选相邻的 2 2 2 堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。 试设计出一个算法,计算出将 …...
Docker快速入门笔记
Docker快速入门 前言 当今软件开发领域的一股热潮正在迅速兴起,它融合了便捷性、灵活性和可移植性,让开发者们欣喜若狂。它就是 Docker!无论你是一个初学者,还是一位经验丰富的开发者,都不能错过这个引领技术浪潮的工…...
【Excel】记录Match和Index函数的用法
最近一直用到的两个处理EXCEL表格数据的函数向大家介绍一下,写这篇博文的目的也是为了记录免得自己忘记了,嘻嘻。 先上百度的链接 Match函数的用法介绍:https://jingyan.baidu.com/article/2fb0ba40b4933941f3ec5f71.html 小结:…...
SolidUI社区-从开源社区角度思考苹果下架多款ChatGPT应用
文章目录 背景下架背景下架原因趋势SolidUI社区的未来规划结语如果成为贡献者 背景 随着文本生成图像的语言模型兴起,SolidUI想帮人们快速构建可视化工具,可视化内容包括2D,3D,3D场景,从而快速构三维数据演示场景。SolidUI 是一个创新的项目…...
插入排序讲解
插入排序(Insertion-Sort)一般也被称为直接插入排序。对于少量元素的排序,它是一个有效的算法。插入排序是一种最简单的排序方法,它的基本思想是将一个记录插入到已经排好序的有序表中,从而一个新的、记录数增1的有序表…...
杀疯了的ChatGPT——开启AI智能交流新纪元 「文末有彩蛋」
欢迎打开 ChatGPT 的新世纪大门 🌍 目录 😊 引言😎 ChatGPT 的高级之处1. 巨大的模型规模2. 广泛的知识覆盖3. 零样本学习4. 多语言支持5. 上下文感知对话 🤖 如何使用 ChatGPT1. 智能助手2. 个性化交互3. 语言学习伙伴4. 创造性写…...
web爬虫第五弹 - JS逆向入门(猿人学第一题)
0- 前言 爬虫是一门需要实战的学问。 而对于初学者来说,要想学好反爬,js逆向则是敲门砖。今天给大家带来一个js逆向入门实例,接下来我们一步一步来感受下入门的逆向是什么样的。该案例选自猿人学练习题。猿人学第一题 1- 拿到需求 进入页面…...
P5731 【深基5.习6】蛇形方阵
题目描述 给出一个不大于 9 9 9 的正整数 n n n,输出 n n n\times n nn 的蛇形方阵。 从左上角填上 1 1 1 开始,顺时针方向依次填入数字,如同样例所示。注意每个数字有都会占用 3 3 3 个字符,前面使用空格补齐。 输入格式…...
Python实现GA遗传算法优化循环神经网络回归模型(LSTM回归算法)项目实战
说明:这是一个机器学习实战项目(附带数据代码文档视频讲解),如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 遗传算法(Genetic Algorithm,GA)最早是由美国的 John holland于20世…...
ESD防静电监控系统在SMT产线中的应用案例
作为电子厂的关键制造环节之一,SMT(表面贴装技术)产线的效率和质量对企业的竞争力至关重要。为了提高生产线的管理效率和保障生产环境的质量,许多电子厂开始采用MES生产管理系统和ESD防静电监控系统的综合解决方案。 在SMT产线中安…...
Vue+Nodejs+Express+Minio 实现本地图片上传
安装Minio,Minio server和Minio client都要下载可以自定义安装目录 安装完成之后,可以将minio配置成环境变量方便使用 配置了环境变量启动命令式 minio server start,默认账号密码minioadmin和minioadmin,点击9000端口的这个链接,即可访问客户端 nodejs连接Minio,简易服务进…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...
