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

设计模式九:组合模式(Composite Pattern)

组合模式是一种结构型设计模式,它允许我们将对象组合成树形结构来表示“整体-部分”层次关系。组合模式使得用户可以以相同的方式处理单个对象和组合对象。
在组合模式中,有两种主要类型的对象:叶子对象和组合对象。叶子对象代表树结构中的最终节点,它们没有子节点。而组合对象代表树结构中的中间节点,它们可以包含子节点。
通过使用组合模式,我们可以创建具有嵌套结构的对象,并且可以递归地处理这些对象。这种递归性质使得组合模式非常适用于处理树状数据结构,例如文件系统、组织架构等。

组合模式的一些特点:

组合模式可以帮助我们简化对树形结构的操作,并提供更灵活的方式来处理对象间的层次关系。它在许多应用领域中都有广泛的应用,特别是在图形用户界面、文件系统和组织架构等方面

  • 通过接口或抽象类定义统一的操作方法,使得客户代码可以透明地处理单个对象和组合对象。
  • 具体的叶子对象和组合对象都实现这个接口或继承这个抽象类,并实现自己特定的操作方法。
  • 组合对象可以包含其他组合对象或叶子对象,从而形成树形结构。
  • 可以在运行时动态地添加、删除或修改组合对象。
  • 客户代码可以通过递归遍历整个树状结构来执行操作。

组合模式是一种结构型设计模式,它将对象组合成树形结构以表示"部分-整体"的层次结构。该模式使得用户可以统一处理单个对象和组合对象,而无需区分它们的具体类型。

组合模式适用于以下场景:

组合模式适用于需要处理部分-整体关系的场景,并且希望以统一的方式对单个对象和组合对象进行操作的情况。它可以简化对象结构的表示和操作,提高系统的灵活性和可扩展性

  1. 需要表示对象的部分-整体层次结构,且希望能够以统一的方式处理其中的所有对象。例如,文件系统中的文件夹和文件之间的关系,可以使用组合模式来表示并提供统一的操作接口。
  2. 希望客户端对单个对象和组合对象进行一致的操作,并且不需要关心对象的具体类型。通过组合模式,客户端可以将对组合对象的操作委托给其子对象,而无需知道具体执行的是单个对象还是整个组合。
  3. 需要对树状结构进行递归遍历,在每个节点上执行相同的操作。组合模式可简化遍历操作的实现,通过递归地遍历组合对象的每个子对象,可以方便地操作整个树状结构。
  4. 希望为对象提供嵌套复制的功能,以便在需要时可以轻松地创建对象的副本。组合模式可简化对象的复制过程,通过递归地复制组合对象的每个子对象,可以实现整个树状结构的深度复制。

组合模式的主要角色

  1. Component(组件):定义叶子节点和容器节点的抽象接口,声明了在树状结构中所有对象共有的操作方法。它可以是一个抽象类或接口,提供了默认的实现或者一些通用的操作。
  2. Leaf(叶子节点):是组合中的叶子对象,表示树状结构中的最底层节点。叶子节点没有子节点,只能执行具体的操作,不能增加或删除子节点。
  3. Composite(容器节点):是组合中的容器对象,可以包含其他的叶子节点和容器节点。容器节点实现了Component接口,并可以对其子节点进行增加、删除和遍历等操作。
  4. Client(客户端):通过Component接口与组合中的对象进行交互,可以使用统一的方式处理叶子节点和容器节点。客户端不需要知道具体的对象类型,只需要通过Component接口来访问和操作对象。
    在组合模式中,容器节点和叶子节点都可以作为树状结构的节点,但它们之间的职责是不同的。叶子节点负责执行具体的操作,而容器节点负责管理子节点并提供一些与子节点相关的操作。通过这种方式,组合模式能够统一处理单个对象和组合对象,使得整个树状结构能够以一致的方式进行操作和管理。

java代码实例

import java.util.ArrayList;
import java.util.List;// 组件接口
interface Component {void operation();
}// 叶子节点
class Leaf implements Component {private String name;public Leaf(String name) {this.name = name;}@Overridepublic void operation() {System.out.println("执行叶子节点:" + name);}
}// 容器节点
class Composite implements Component {private List<Component> children = new ArrayList<>();public void add(Component component) {children.add(component);}public void remove(Component component) {children.remove(component);}@Overridepublic void operation() {System.out.println("执行容器节点");for (Component component : children) {component.operation();}}
}public class Main {public static void main(String[] args) {// 创建树状结构Composite root = new Composite();Composite branch1 = new Composite();branch1.add(new Leaf("叶子节点1"));branch1.add(new Leaf("叶子节点2"));Composite branch2 = new Composite();branch2.add(new Leaf("叶子节点3"));branch2.add(new Leaf("叶子节点4"));root.add(branch1);root.add(branch2);// 执行操作root.operation();}
}

在上面的示例中,我们首先定义了Component接口作为组件的抽象。然后,实现了叶子节点Leaf和容器节点Composite。叶子节点只能执行具体的操作,而容器节点可以管理子节点并执行一些操作。
在Composite类中,通过List来管理子节点,并提供了添加和删除子节点的方法。在operation方法中,遍历所有子节点并执行它们的操作。

组合模式的优缺点

组合模式的优点:

  1. 简化客户端代码:组合模式通过统一叶子节点和容器节点的接口,使得客户端可以统一对待它们。客户端不需要知道具体是处理单个对象还是某个组合对象,从而简化了客户端的代码。
  2. 灵活性和可扩展性:由于叶子节点和容器节点共享相同的接口,因此可以很容易地添加新的叶子节点或容器节点,从而增加系统的灵活性和可扩展性。
  3. 递归结构:组合模式通过递归结构实现了对象间的层次关系,这使得我们可以使用递归算法在整个组合结构中进行操作。

组合模式的缺点:

  1. 可能导致设计过度复杂:当组合结构非常复杂时,可能会导致实现和理解变得困难。过度使用组合模式可能会导致系统的复杂性增加。
  2. 不适用于每个场景:组合模式适用于树状结构中的组件,但并不是所有的场景都符合这种结构。如果场景不适合树状结构,使用组合模式可能会引入不必要的复杂性。

总之,组合模式适用于需要处理树状结构并且希望统一对待单个对象和组合对象的场景。它能够简化客户端代码,提供灵活性和可扩展性,但需要注意不要过度复杂化设计,并且仔细考虑是否适用于特定的场景。

相关文章:

设计模式九:组合模式(Composite Pattern)

组合模式是一种结构型设计模式&#xff0c;它允许我们将对象组合成树形结构来表示“整体-部分”层次关系。组合模式使得用户可以以相同的方式处理单个对象和组合对象。 在组合模式中&#xff0c;有两种主要类型的对象&#xff1a;叶子对象和组合对象。叶子对象代表树结构中的最…...

【COlor传感器】通过扰动调制光传感实现智能光传输的占用分布估计研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

微服务系列<3>---微服务的调用组件 rpc 远程调用

什么是rpc调用,让我们调用远程方法就像调用本地方法一样 这就属于rpc调用 rpc是针对于本地来说的 调用远程方法根调用本地方法一样 如果能达到这种效果 就是rpc调用如果达到一种效果 调用远程和调用本地一样 他就是一种rpc框架2个微服务 之间发的调用 我们之前通过ribbon的方式…...

P1558 色板游戏

题目链接 题目要求实现区间覆盖修改以及区间数量查询&#xff0c;不难想到为线段树&#xff0c;而需要维护什么值来得到不同数的数量很难想&#xff0c;但是我们注意到颜色的数量最多只有30种&#xff0c;所以对于每一种颜色在一个区间中是否存在&#xff0c;我们可以使用线段树…...

大数据概论

1、大数据概念 大数据(Big Data): 指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合&#xff0c;是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产 大数据主要解决&#xff0c;海量数据的采集、存储和分…...

数据库访问中间件--springdata-jpa的基本使用

二、单表SQL操作-使用关键字拼凑方法 回顾 public interface UserRepository extends JpaRepository<User,Integer> {User findByUsernameLike(String username); }GetMapping("/user/username/{username}")public Object findUserByUsername(PathVariable S…...

c++游戏制作指南(二):制作一个炫酷的启动界面(c++绘图)

&#x1f37f;*★,*:.☆(&#xffe3;▽&#xffe3;)/$:*.★* &#x1f37f; &#x1f35f;欢迎来到静渊隐者的csdn博文&#xff0c;本文是c游戏制作指南的一部&#x1f35f; &#x1f355;更多文章请点击下方链接&#x1f355; &#x1f368; c游戏制作指南&#x1f3…...

spring.config.location 手动指定配置文件文件

–spring.config.locationD:\javaproject\bangsun\ds-admin\ds-oper-mgr\src\main\resources\application.yml...

【uniapp 使用ECharts】

Uniapp可以使用ECharts进行数据可视化&#xff0c;需要按照以下步骤进行操作&#xff1a; 1. 安装ECharts插件 可以使用npm安装echarts插件&#xff0c;命令如下&#xff1a; npm install echarts --save2. 引入ECharts插件 在需要使用ECharts的页面中引入ECharts插件&…...

数据结构--线性表2-2

目录 一、线性表例题&#xff1a; 二、分配动态内存&#xff1a; 1.动态创建一个空顺序表的算法&#xff1a; 2.动态顺序表的插入算法&#xff1a; 3.动态顺序表的删除 三、线性表的链式表示和实现 例题1&#xff1a;创建链表并插入26个字母 例题2&#xff1a;在链表中取…...

利用openTCS实现车辆调度系统(一)系统介绍

系统介绍 openTCS简介 官方的回答&#xff1a; openTCS&#xff08;开放式运输控制系统的缩写&#xff09;是一种免费的控制系统软件&#xff0c;用于协调自动导引车&#xff08;AGV&#xff09;和移动机器人车队&#xff0c;例如在生产工厂中。 通常应该可以控制任何具有通信…...

销存管理系统ssm进销存仓库销售java jsp源代码mysql

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 销存管理系统ssm 系统有1权限&#xff1a;管理员 二…...

【Axure教程】移动端二级滑动选择器

今天教大家制作移动端二级滑动选择器的原型模板&#xff0c;该原型已全国一二级省市选择器为案例&#xff0c;因为该原型用中继器做的&#xff0c;所以制作完成之后使用也很方便&#xff0c;只需修改中继器表格里的内容即可 一、效果展示 1. 拖动选择 2. 快捷选择 【原型预览…...

PHP操作solr

1&#xff0c;php下载solr(索尔)扩展&#xff0c;phpinfo需要支持solr扩展. 2&#xff0c;安装 Solr。Solr 要求您的系统上有 Java。java –version&#xff0c;Java 的版本大于 1.6 3&#xff0c;下载solr,并安装 D:\solr。 开启solr命令&#xff1a;solr start 关闭solr命令:…...

leetcode 46. Permutations(排列)

返回数组nums中数字的所有可能的排列组合。 思路&#xff1a; 排列组合这种一般会想到DFS。 这个排列中每个数字只能用一次&#xff0c; 可用如下DFS流程 stack.push(num); dfs(nums, num); stack.pop();退出条件&#xff1a; 当stack的size和nums数组一样时&#xff0c;说…...

5、二叉树

二叉树遍历 递归序 public static void f(Node head) {if (head == null) {return;}f(head.left);f(head.right); }前中后遍历_递归 public static void preOrderRecur(Node head) {if (head == null) {return;}System.out.print(head.value + " ");preOrderRecur…...

Doris比MySQL快的原因

简介 在数据存储和数据分析领域&#xff0c;MySQL和Doris是比较流行的数据库管理系统的代表。 在如今的大数据时代&#xff0c;数据量和数据分析的速度是很重要的。 在数据分析和数据处理中&#xff0c;Doris比MySQL快&#xff0c;这个问题一直是许多人关心的问题。 Doris的数…...

Prometheus + Grafana安装

Prometheus是一款基于时序数据库的开源监控告警系统&#xff0c;非常适合Kubernetes集群的监控。Prometheus的基本原理是通过HTTP协议周期性抓取被监控组件的状态&#xff0c;任意组件只要提供对应的HTTP接口就可以接入监控。不需要任何SDK或者其他的集成过程。这样做非常适合做…...

二十三种设计模式第二十一篇--解释器模式

解释器模式&#xff08;Interpreter Pattern&#xff09;是一种行为设计模式&#xff0c;它用于定义一种语言的语法结构和解释器&#xff0c;使得可以解释并执行特定的语法规则。该模式可以将复杂的语言表达式分解为更小的语法单元&#xff0c;并定义其解释过程。 解释器模式的…...

PHP8的数据类型转换-PHP8知识详解

什么是数据类型转换&#xff1f; 答&#xff1a;数据从一个类型转换成另外一个类型&#xff0c;就是数据类型转换。 在PHP8中&#xff0c;变量的类型就是由赋值决定的&#xff0c;也就是说&#xff0c;如果 string 赋值给 $var&#xff0c;然后 $var 的类型就是 string。之后…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互

引擎版本&#xff1a; 3.8.1 语言&#xff1a; JavaScript/TypeScript、C、Java 环境&#xff1a;Window 参考&#xff1a;Java原生反射机制 您好&#xff0c;我是鹤九日&#xff01; 回顾 在上篇文章中&#xff1a;CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的

修改bug思路&#xff1a; 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑&#xff1a;async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用

一、方案背景​ 在现代生产与生活场景中&#xff0c;如工厂高危作业区、医院手术室、公共场景等&#xff0c;人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式&#xff0c;存在效率低、覆盖面不足、判断主观性强等问题&#xff0c;难以满足对人员打手机行为精…...

适应性Java用于现代 API:REST、GraphQL 和事件驱动

在快速发展的软件开发领域&#xff0c;REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名&#xff0c;不断适应这些现代范式的需求。随着不断发展的生态系统&#xff0c;Java 在现代 API 方…...

SQL Server 触发器调用存储过程实现发送 HTTP 请求

文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...

LangChain 中的文档加载器(Loader)与文本切分器(Splitter)详解《二》

&#x1f9e0; LangChain 中 TextSplitter 的使用详解&#xff1a;从基础到进阶&#xff08;附代码&#xff09; 一、前言 在处理大规模文本数据时&#xff0c;特别是在构建知识库或进行大模型训练与推理时&#xff0c;文本切分&#xff08;Text Splitting&#xff09; 是一个…...