组合模式 Composite Pattern

news/2025/2/22 0:26:42/

https://en.wikipedia.org/wiki/Composite_pattern

组合模式是一种结构型设计模式。组合模式描述了一组对象,这些对象被视为同一类型对象的单个实例。组合的目的是将对象“组合「compose」”成树结构,以表示部分-整体层次结构。实现组合模式可以让客户端统一处理单个对象和组合。

解决的问题

表示 part-whole 层次结构,以便客户端可以统一处理部分和整体对象。
将 part-whole 层次表示为树结构。
在定义(1)Part对象和(2)充当Part对象容器的Whole对象时,客户端必须单独处理它们,这会使客户端代码复杂化。

解决方案

为 part(Leaf)对象和 whole(Composite)对象定义统一的Component接口。
单个Leaf对象直接实现Component接口,Composite对象将请求转发到其子组件。

这使客户端能够通过Component接口统一处理Leaf和Composite对象:Leaf对象直接执行请求,Composite对象沿树结构向下递归地将请求转发给其子组件。这使得客户端类更容易实现、更改、测试和重用。

另请参见下面的UML类和对象图「object diagram」。

UML class and object diagram

在上面的UML类图中,Client类没有直接(separately)引用Leaf和Composite类。相反,客户端引用公共 Component 接口,可以统一处理Leaf和Composite。
Leaf类没有子类,直接实现Component接口。
Composite类维护一个Component子对象(children)的容器,并将请求转发给这些子对象(对于children中的每个子对象:child.operation())。

对象协作图「object collaboration diagram」显示了运行时交互:在这个例子中,Client对象向树结构中的顶级Composite对象(Component类型)发送请求。请求被转发到树结构下方的所有子组件对象(Leaf 和 Composite对象)。

Defining Child-Related Operations

有两种设计变体「variants」用于定义和实现与子组件相关的操作「child-related operations」,例如向容器中添加/从容器中删除子组件(add(child)/remove(child))和访问子组件(getChild()):

        1,一致性设计「Design for uniformity」:在Component接口中定义与child相关的操作。这使得客户端可以统一地处理Leaf和Composite对象。但是类型安全性丢失了,因为客户端可以对Leaf对象执行与child对象相关的操作。
        2,为类型安全而设计「Design for type safety:」:与child相关的操作仅在Composite类中定义。客户端必须区别对待Leaf和Composite对象。但是类型安全是可以获得的,因为客户端不能在Leaf对象上执行与子对象相关的操作。

组合设计模式强调一致性而不是类型安全性。

UML class diagram

Component

        是所有组件的抽象,包括Composite 组件
        声明组合中「composition」对象的接口
        (可选)定义了一个用于访问递归结构中组件父级的接口,并在适当的情况下实现它

Leaf

        表示组合中「composition」的叶子对象
        实现所有Component方法

Composite
        表示组合组件(具有子组件的组件)
        实现操纵children的方法
        实现所有Component方法,通常是通过将它们委托给其 children

Variation

​该模式还涉及在主 Component 接口中包含 child-manipulation 方法,而不仅仅是Composite子类。最近的描述有时会省略这些方法。

举个例子

假设我们要设计一个文件系统,文件系统中有文件和文件夹:

  • 文件是叶子节点,没有子节点。

  • 文件夹是容器节点,可以包含文件或其他文件夹。

使用组合模式

  1. Component:定义一个抽象类 FileSystemComponent,包含一个方法 display()

  2. LeafFile 类继承 FileSystemComponent,实现 display() 方法。

  3. CompositeFolder 类继承 FileSystemComponent,包含一个子节点列表,并实现 display() 方法(递归显示所有子节点)。

客户端可以统一调用 display() 方法,无论是文件还是文件夹。


优点

  1. 简化客户端代码:客户端无需区分叶子节点和容器节点,统一处理。

  2. 扩展性强:可以轻松添加新的组件类型。

  3. 符合开闭原则:对扩展开放,对修改关闭。


缺点

  1. 设计复杂:需要定义统一的接口,可能增加系统的复杂性。

  2. 类型检查问题:在某些情况下,客户端可能需要检查对象的具体类型。


适用场景

  1. 需要表示“部分-整体”的层次结构。

  2. 希望客户端以统一的方式处理单个对象和组合对象。

  3. 需要动态地添加或删除组件。

from abc import ABC, abstractmethod# Component
class FileSystemComponent(ABC):@abstractmethoddef display(self):pass# Leaf
class File(FileSystemComponent):def __init__(self, name):self.name = namedef display(self):print(f"File: {self.name}")# Composite
class Folder(FileSystemComponent):def __init__(self, name):self.name = nameself.children = []def add(self, component):self.children.append(component)def remove(self, component):self.children.remove(component)def display(self):print(f"Folder: {self.name}")for child in self.children:child.display()# Client
if __name__ == "__main__":file1 = File("file1.txt")file2 = File("file2.txt")folder1 = Folder("Folder1")folder1.add(file1)folder1.add(file2)folder2 = Folder("Folder2")folder2.add(File("file3.txt"))folder2.add(folder1)folder2.display()


http://www.ppmy.cn/news/1573729.html

相关文章

【系统架构】分布式事务模型详解

1. 分布式基础理论 1.1 CAP理论 CAP 理论可以表述为,一个分布式系统最多只能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition Tolerance)这三项中的两项。 一致性是…

win11 终端乱码导致IDE 各种输出也乱码

因为 win11 终端乱码导致IDE 各种输出也乱码导致作者对此十分头大。所以研究了各种方法。 单独设置终端编码对 HKEY_CURRENT_USER\Console 注册表进行修改对 HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processo 注册表进行修改使用命令[Console]::OutputEncoding [Syst…

微软的基本类库BCL

微软的 基本类库(Base Class Library, BCL) 是 .NET 框架和 .NET Core/.NET 5 的核心组成部分,提供了大量的类、接口和值类型,用于支持各种常见的编程任务。BCL 是开发 .NET 应用程序的基础,几乎所有的 .NET 应用程序都…

Java 第六章 集合(1)

目录 集合概述 创建集合的原因: 集合框架 ​编辑 Collection接口 List 接口及实现类 实现类 数组与链表 ArrayList的常用方法 增加: 删除: 替换: 判断: 查询: 转换: List接口集…

DeepSeek等大模型功能集成到WPS中的详细步骤

记录下将**DeepSeek功能集成到WPS中**的步骤,以备忘。 1. 下载并安装OfficeAI插件 访问OfficeAI插件下载地址:https://www.office-ai.cn/,下载插件(目前只支持windows系统)。 注意,有两个插件&#xff0…

frameworks 之 Activity添加View

frameworks 之 Activity添加View 1 LaunchActivityItem1.1 Activity 创建1.2 PhoneWindow 创建1.3 DecorView 创建 2 ResumeActivityItem 讲解 Activity加载View的时机和流程 涉及到的类如下 frameworks/base/core/java/android/app/Activity.javaframeworks/base/services/cor…

数智驱动:医学编程与建模技术在智慧医院AI建设中的创新与变革

一、引言 1.1 研究背景与意义 在信息技术飞速发展的数智化时代,医疗行业正经历着深刻变革,医院的发展模式也在不断转型升级。随着人口老龄化加剧、疾病谱的变化以及人们对医疗服务质量要求的日益提高,传统的医疗模式已难以满足社会的需求,智慧医院建设成为医疗行业发展的…

嵌入式学习(18)---Linux文件编程中的进程

一、进程的概念 进程:(用来描述 程序动态执行的过程,方便操作系统管理的) 进行中的程序 程序的一次执行过程 (内存 CPU) 程序的实例 程序 ----加载到内存----> 进程 应用场景: 实现并发 同一时刻 同时发生 并行 …