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

设计模式-结构型-组合模式

1. 什么是组合模式?

组合模式(Composite Pattern) 是一种结构型设计模式,它允许将对象组合成树形结构来表示“部分-整体”的层次结构。组合模式使得客户端对单个对象和组合对象的使用具有一致性。换句话说,组合模式允许你将多个对象组合成一个复合对象,然后统一处理这些对象

核心思想

组合模式通过将简单对象(叶子节点)和复合对象(包含子对象的树形结构)统一视为相同的类型,从而简化客户端对不同类型对象的处理。它常用于表示树形结构,如目录结构、组织架构等。


2. 组合模式的结构

UML 类图

以下是组合模式的 UML 类图:

角色

  1. Component(抽象组件)
    定义了所有对象(无论是叶子节点还是组合节点)共用的方法,如 operation()。可以是抽象类或接口。

  2. Leaf(叶子节点)
    叶子节点是组合树结构的最底层元素,不能再包含子对象。它实现了 operation() 方法,通常用于具体的操作。

  3. Composite(组合节点)
    组合节点包含叶子节点或其他组合节点。它也实现了 operation() 方法,并允许对子节点进行操作(如 add()remove() 等)。通常用来组织和管理子组件。


3. 组合模式的示例

场景描述

假设我们需要构建一个文件系统的树形结构,其中包含文件夹(可以包含文件和子文件夹)和文件。文件和文件夹都有一个 display() 方法。组合模式可以帮助我们统一处理文件和文件夹。

代码实现

from abc import ABC, abstractmethod# 抽象组件类
class FileSystemComponent(ABC):@abstractmethoddef display(self):pass# 叶子节点:文件类
class File(FileSystemComponent):def __init__(self, name):self.name = namedef display(self):print(f"File: {self.name}")# 组合节点:文件夹类
class Folder(FileSystemComponent):def __init__(self, name):self.name = nameself.children = []def add(self, component: FileSystemComponent):self.children.append(component)def remove(self, component: FileSystemComponent):self.children.remove(component)def display(self):print(f"Folder: {self.name}")for child in self.children:child.display()# 测试组合模式
if __name__ == "__main__":# 创建文件和文件夹file1 = File("file1.txt")file2 = File("file2.txt")file3 = File("file3.txt")folder1 = Folder("Folder1")folder2 = Folder("Folder2")folder1.add(file1)folder1.add(file2)folder2.add(file3)# 创建根文件夹,添加子文件夹root = Folder("Root")root.add(folder1)root.add(folder2)# 显示整个文件系统结构root.display()

输出

Folder: Root

Folder: Folder1

File: file1.txt

File: file2.txt

Folder: Folder2

File: file3.txt

在上面的代码中,FileSystemComponent 是抽象组件类,File 是叶子节点,Folder 是组合节点。Folder 具有 add()remove() 方法来管理其子节点,而 File 只有 display() 方法。最后,通过调用根文件夹的 display() 方法,能够递归地显示整个文件系统的结构。


4. 组合模式的优缺点

优点

  1. 简化客户端代码
    客户端不需要关心对象是单个对象还是组合对象,它们可以通过相同的接口进行处理,简化了代码结构。

  2. 递归结构清晰
    组合模式特别适合处理递归结构的数据,比如文件系统、组织结构等。

  3. 增加或删除元素方便
    通过组合模式,添加或删除树形结构中的节点(文件或文件夹)非常方便,不影响其它节点的操作。

  4. 高扩展性
    可以轻松扩展新的叶子节点或组合节点,而不需要修改现有的客户端代码。

缺点

  1. 复杂性增加
    如果对象结构本身并不复杂,引入组合模式可能会让系统变得过于复杂,导致不必要的开销。

  2. 不易实现对叶子节点的具体行为
    在某些情况下,叶子节点的行为可能与组合节点有所不同,这可能会导致设计上的矛盾,难以通过统一接口来处理。


5. 组合模式的应用场景

  1. 文件系统
    文件夹可以包含子文件夹和文件,文件和文件夹是不同的对象类型,但是它们都实现了一个公共接口 display(),可以统一处理。

  2. GUI 组件库
    许多图形用户界面组件(如按钮、窗体、标签等)可以通过组合模式来处理。组件(如按钮)可以是叶子节点,而容器(如面板、窗体)可以是组合节点。

  3. 组织架构
    企业的组织架构可以通过组合模式表示。一个部门可以包含多个员工或者子部门,所有部门和员工都可以通过统一的接口进行管理。

  4. 树形结构的表示
    任何需要树形结构表示的场景,例如目录树、家族谱、层次化数据展示等,都适合使用组合模式。


6. 总结

组合模式 是一种非常强大的结构型设计模式,它能够有效地处理树形结构的数据,同时使得客户端代码对单一对象和组合对象的处理保持一致性。通过组合模式,您可以更轻松地管理复杂的对象结构,并且增加或删除节点时不会影响到其他部分。

核心要点

  1. 统一对待单一对象与组合对象
  2. 递归结构使得复杂对象的管理变得简单
  3. 组合模式简化客户端代码,使其更加灵活

相关文章:

设计模式-结构型-组合模式

1. 什么是组合模式? 组合模式(Composite Pattern) 是一种结构型设计模式,它允许将对象组合成树形结构来表示“部分-整体”的层次结构。组合模式使得客户端对单个对象和组合对象的使用具有一致性。换句话说,组合模式允…...

基于Java的推箱子游戏设计与实现

基于Java的推箱子游戏设计与实现 摘 要 社会在进步,人们生活质量也在日益提高。高强度的压力也接踵而来。社会中急需出现新的有效方式来缓解人们的压力。此次设计符合了社会需求,Java推箱子游戏可以让人们在闲暇之余,体验游戏的乐趣。具有…...

Spark vs Flink分布式数据处理框架的全面对比与应用场景解析

1. 引言 1.1 什么是分布式数据处理框架 随着数据量的快速增长,传统的单机处理方式已经无法满足现代数据处理需求。分布式数据处理框架应运而生,它通过将数据分片分布到多台服务器上并行处理,提高了任务的处理速度和效率。 分布式数据处理框…...

python_excel列表单元格字符合并、填充、复制操作

读取指定sheet页,根据规则合并指定列,填充特定字符,删除多余的列,每行复制四次,最后写入新的文件中。 import pandas as pd""" 读取指定sheet页,根据规则合并指定列,填充特定字…...

nums[:]数组切片

问题:给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。 使用代码如下没有办法通过测试示例,必须将最后一行代码改成 nums[:]nums[-k:]nums[:-k]切片形式: 原因:列表的切片操作 …...

【Arthas 】Can not find Arthas under local: /root/.arthas/lib 解决办法

报错 [INFO] JAVA_HOME: /opt/java/openjdk [INFO] arthas-boot version: 4.0.4 [INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER. [1]: 12 org.springframework.boot.loader.JarLauncher 1 [ER…...

录用率23%!CCF推荐-B类,Early Access即可被SCI数据库收录,中美作者占比过半

International Journal of Human-Computer Interaction(IJHCI)创刊于1989年,由泰勒-弗朗西斯(Taylor & Francis, Inc.)出版,主要发表关于交互式计算(认知和人体工程学)、数字无障…...

IP 地址与蜜罐技术

基于IP的地址的蜜罐技术是一种主动防御策略,它能够通过在网络上布置的一些看似正常没问题的IP地址来吸引恶意者的注意,将恶意者引导到预先布置好的伪装的目标之中。 如何实现蜜罐技术 当恶意攻击者在网络中四处扫描,寻找可入侵的目标时&…...

Vue_API文档

Vue API风格 Vue 的组件可以按两种不同的风格书写:选项式 API(Vue2) 和组合式 API(Vue3) 大部分的核心概念在这两种风格之间都是通用的。熟悉了一种风格以后,你也能够很快地理解另一种风格 选项式API(Opt…...

WebSocket 设计思路

WebSocket 设计思路 1. 核心结构体 1.1 Manager (管理器) // Manager 负责管理所有WebSocket连接 type Manager struct {clients sync.Map // 存储所有客户端连接broadcast chan []byte // 广播消息通道messages chan Message // 消息处理通道config *config.WebSo…...

Jenkins持续集成与交付安装配置

Jenkins 是一款开源的持续集成(CI)和持续交付(CD)工具,它主要用于自动化软件的构建、测试和部署流程。为项目持续集成与交付功能强大的应用。下面我们来介绍下它的安装与配置。 环境准备 更新系统组件(这…...

ESP32作为Wi-Fi AP模式的测试

一、AP模式的流程 初始化阶段 (Init Phase): 1.1: Main task(主任务)初始化LwIP(轻量级TCP/IP协议栈)。 ESP_ERROR_CHECK(esp_netif_init()); 1.2: 创建和初始化Event task(事件任务)。 ESP_ERROR_CHECK…...

【爬虫】单个网站链接爬取文献数据:标题、摘要、作者等信息

源码链接: https://github.com/Niceeggplant/Single—Site-Crawler.git 一、项目概述 从指定网页中提取文章关键信息的工具。通过输入文章的 URL,程序将自动抓取网页内容 二、技术选型与原理 requests 库:这是 Python 中用于发送 HTTP 请求…...

Android RIL(Radio Interface Layer)全面概述和知识要点(3万字长文)

在Android面试时,懂得越多越深android framework的知识,越为自己加分。 目录 第一章:RIL 概述 1.1 RIL 的定义与作用 1.2 RIL 的发展历程 1.3 RIL 与 Android 系统的关系 第二章:RIL 的架构与工作原理 2.1 RIL 的架构组成 2.2 RIL 的工作原理 2.3 RIL 的接口与协议…...

leetcode_2816. 翻倍以链表形式表示的数字

2816. 翻倍以链表形式表示的数字 - 力扣(LeetCode) 搜先看到这个题目 链表的节点那么多 已经远超longlong能够表示的范围 那么暴力解题 肯定是不可以的了 我们可以想到 乘法运算中 就是从低位到高位进行计算 刚开始 我想先反转链表 然后在计算 然后在进…...

【论文阅读】MAMBA系列学习

Mamba code:state-spaces/mamba: Mamba SSM architecture paper:https://arxiv.org/abs/2312.00752 背景 研究问题:如何在保持线性时间复杂度的同时,提升序列建模的性能,特别是在处理长序列和密集数据(如…...

MySQL教程之:批量使用mysql

在前几节中&#xff0c;您以交互方式使用mysql输入语句并查看结果。您也可以运行mysql批量模式。为此&#xff0c;请将要运行的语句放在文件中&#xff0c;然后告诉mysql从文件中读取其输入&#xff1a; $> mysql < batch-file 如果您在Windows下运行mysql&#xff0c;…...

17_Redis管道技术

Redis管道(Pipeline)技术是一种在 Redis 客户端与服务器之间进行高效数据交互的技术。 1.Redis管道技术介绍 1.1 传统请求响应模式 在传统的请求-响应模式下,客户端每发送一个命令后会等待服务器返回结果,然后再发送下一个命令。这种方式在网络延迟较高的情况下会导致性…...

【LC】3270. 求出数字答案

题目描述&#xff1a; 给你三个 正 整数 num1 &#xff0c;num2 和 num3 。 数字 num1 &#xff0c;num2 和 num3 的数字答案 key 是一个四位数&#xff0c;定义如下&#xff1a; 一开始&#xff0c;如果有数字 少于 四位数&#xff0c;给它补 前导 0 。答案 key 的第 i 个数…...

【redis】ubuntu18安装redis7

在Ubuntu 18下安装Redis7可以通过以下两种方法实现&#xff1a;手动编译安装和使用APT进行安装。 Ubuntu 18系统的环境和版本&#xff1a; $ cat /proc/version Linux version 4.15.0-213-generic (builddlcy02-amd64-079) (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

Go 语言并发编程基础:无缓冲与有缓冲通道

在上一章节中&#xff0c;我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道&#xff0c;它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好&#xff0…...