当前位置: 首页 > 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)…...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

安卓基础(aar)

重新设置java21的环境&#xff0c;临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的&#xff1a; MyApp/ ├── app/ …...

#Uniapp篇:chrome调试unapp适配

chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器&#xff1a;Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析

Linux 内存管理实战精讲&#xff1a;核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用&#xff0c;还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...