设计模式- 组合模式(Composite)结构|原理|优缺点|场景|示例

本文主要是介绍设计模式- 组合模式(Composite)结构|原理|优缺点|场景|示例,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

                            ​​​​​​​        设计模式(分类)        设计模式(六大原则)   

    创建型(5种)        工厂方法         抽象工厂模式        单例模式        建造者模式        原型模式

    结构型(7种)        适配器模式        装饰器模式        代理模式        ​​​​​​外观模式      桥接模式        组合模式       享元模式

    行为型(11种)      策略模式        模板方法模式        观察者模式        迭代器模式        责任链模式        命令模式

                                   备忘录模式          状态模式          访问者模式        中介者模式    


组合模式(Composite Pattern)是一种结构型设计模式,它允许你将对象组合成树形结构来表示“部分-整体”的层次结构。这种模式使得客户端可以以一致的方式处理单个对象(叶子节点)和组合对象(容器节点),无需关心处理的是个体还是群体。组合模式使得你可以将对象看作是树形结构中的节点,节点可以是简单的对象,也可以是包含其他节点的复合对象,这样就能形成一个层次化的结构。

模式结构

组合模式主要涉及以下几个角色:

  1. Component(抽象组件)

    • 定义了所有对象(包括叶子节点和容器节点)共享的公共接口。这个接口规定了如何访问和管理对象的子部件。
    • 通常会提供一个方法来添加、删除子组件,以及遍历子组件的方法。
  2. Leaf(叶子组件)

    • 是组合结构的终端节点,不包含任何子组件。
    • 实现Component接口,但对于那些与子组件管理无关的方法(如添加、删除子组件),可以提供空实现或者抛出异常。
  3. Composite(容器组件)

    • 包含一个或多个子组件,每个子组件也是Component的实例。
    • 实现Component接口,提供与管理子组件相关的方法的实际逻辑,如添加、删除子组件以及遍历子组件。
    • 可能会提供一些额外的方法来管理子组件集合,但这些方法通常不暴露给客户端。

工作原理

  • 客户端:通过Component接口与系统交互,无需区分处理的是叶子节点还是容器节点。
  • Component:定义了通用接口,为所有组件(包括叶子和容器)提供一致性。
  • Leaf:实现Component接口,但不包含子组件,因此与子组件管理相关的操作为空或无效。
  • Composite:除了实现Component接口外,还持有子组件的集合,并提供操作子组件的方法。当客户端请求操作时,Composite会递归地将请求传递给它的子组件。

优缺点

优点
  • 单一职责原则:组合模式使得叶子节点和容器节点都遵循单一职责原则,各自专注于自己的功能。
  • 透明性:客户端可以一致地处理单个对象和组合对象,无需知道处理的是叶子还是容器,提高了代码的透明性和简洁性。
  • 易于扩展:新类型的组件只需继承Component或实现相关接口即可加入到组合结构中,不影响已有代码。
缺点
  • 设计复杂度增加:为了实现组合模式,需要设计额外的抽象层和接口,使得系统变得相对复杂。
  • 递归操作可能导致性能问题:如果组合结构非常深,递归操作可能会导致栈溢出或效率下降。

适用场景

  • 系统需要处理对象的“部分-整体”关系:当需要表示对象的层级结构时,组合模式可以很好地表示这种关系。
  • 希望客户端以一致的方式处理单个对象和组合对象:组合模式使得客户端无需关心处理对象的具体类型,简化了客户端代码。
  • 希望简化新组件类型的添加:新的叶子节点或容器节点只需要符合Component接口即可轻松融入现有系统。

代码示例(以Java为例)

// 抽象组件
interface Component {void add(Component component);void remove(Component component);void operation();
}// 叶子节点
class Leaf implements Component {private String name;public Leaf(String name) {this.name = name;}@Overridepublic void add(Component component) {throw new UnsupportedOperationException("Leaves cannot have children.");}@Overridepublic void remove(Component component) {throw new UnsupportedOperationException("Leaves cannot have children.");}@Overridepublic void operation() {System.out.println("Leaf " + name + " performing operation.");}
}// 容器节点
class Composite implements Component {private List<Component> children = new ArrayList<>();private String name;public Composite(String name) {this.name = name;}@Overridepublic void add(Component component) {children.add(component);}@Overridepublic void remove(Component component) {children.remove(component);}@Overridepublic void operation() {System.out.println("Composite " + name + " performing operation.");for (Component child : children) {child.operation();}}
}// 客户端代码
public class CompositePatternDemo {public static void main(String[] args) {Component root = new Composite("Root");root.add(new Leaf("Leaf A"));root.add(new Leaf("Leaf B"));Component branch = new Composite("Branch");branch.add(new Leaf("Leaf C"));branch.add(new Leaf("Leaf D"));root.add(branch);root.operation();}
}

在这个Java示例中:

  • Component接口定义了所有组件(叶子和容器)的通用接口,包括添加、删除子组件和执行操作的方法。
  • Leaf类实现了Component接口,但其addremove方法抛出异常,表示叶子节点无法添加或删除子节点。operation方法输出叶子节点执行操作的信息。
  • Composite类同样实现了Component接口,并维护了一个List<Component>来存储子组件。addremove方法实现了对子组件的增删操作。operation方法不仅执行自身操作,还递归地调用其子组件的operation方法。
  • 客户端代码创建了一个树状结构,并通过调用根节点的operation方法,以一致的方式处理整个组合结构中的所有组件。

 代码示例(以Python为例)

from abc import ABC, abstractmethodclass FileSystemObject(ABC):"""抽象组件(Component)"""def __init__(self, name):self.name = name@abstractmethoddef add(self, child):pass@abstractmethoddef remove(self, child):pass@abstractmethoddef get_child(self, index):pass@abstractmethoddef operation(self):passclass File(FileSystemObject):"""叶子组件(Leaf)"""def add(self, child):raise TypeError("Cannot add children to a file")def remove(self, child):raise TypeError("Cannot remove children from a file")def get_child(self, index):raise IndexError("Files do not have children")def operation(self):return f"Performing operation on file: {self.name}"class Directory(FileSystemObject):"""复合组件(Composite)"""def __init__(self, name):super().__init__(name)self.children = []def add(self, child):self.children.append(child)def remove(self, child):self.children.remove(child)def get_child(self, index):return self.children[index]def operation(self):result = f"Performing operation on directory: {self.name}\n"for child in self.children:result += child.operation() + "\n"return result# 客户端代码
if __name__ == "__main__":root_dir = Directory("root")dir_a = Directory("dir_a")dir_b = Directory("dir_b")file_1 = File("file_1.txt")file_2 = File("file_2.txt")root_dir.add(dir_a)root_dir.add(dir_b)dir_a.add(file_1)dir_b.add(file_2)print(root_dir.operation())

 在这个Python示例中:

  • FileSystemObject是抽象组件,使用abc模块中的ABC类和abstractmethod装饰器定义了所有文件系统对象共有的接口,如添加、删除子对象和执行操作等。
  • File类作为叶子组件,继承自FileSystemObject,实现了operation方法,并且其addremoveget_child方法抛出异常,表示文件不能包含子对象。
  • Directory类作为复合组件,同样继承自FileSystemObject,并且维护了一个children列表来存储子对象(可以是文件或子目录)。addremoveget_child方法实现了对子对象的管理。operation方法不仅执行自身操作,还递归地调用其子对象的operation方法,从而处理整个目录树。

客户端代码创建了根目录、子目录以及文件,并建立了它们之间的层级关系。最后,通过调用根目录的operation方法,以一致的方式处理整个文件系统的对象,无论是单个文件还是包含多个子对象的目录。

这篇关于设计模式- 组合模式(Composite)结构|原理|优缺点|场景|示例的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/930961

相关文章

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

在 Spring Boot 中使用 @Autowired和 @Bean注解的示例详解

《在SpringBoot中使用@Autowired和@Bean注解的示例详解》本文通过一个示例演示了如何在SpringBoot中使用@Autowired和@Bean注解进行依赖注入和Bean... 目录在 Spring Boot 中使用 @Autowired 和 @Bean 注解示例背景1. 定义 Stud

oracle DBMS_SQL.PARSE的使用方法和示例

《oracleDBMS_SQL.PARSE的使用方法和示例》DBMS_SQL是Oracle数据库中的一个强大包,用于动态构建和执行SQL语句,DBMS_SQL.PARSE过程解析SQL语句或PL/S... 目录语法示例注意事项DBMS_SQL 是 oracle 数据库中的一个强大包,它允许动态地构建和执行

Python中顺序结构和循环结构示例代码

《Python中顺序结构和循环结构示例代码》:本文主要介绍Python中的条件语句和循环语句,条件语句用于根据条件执行不同的代码块,循环语句用于重复执行一段代码,文章还详细说明了range函数的使... 目录一、条件语句(1)条件语句的定义(2)条件语句的语法(a)单分支 if(b)双分支 if-else(

Python中Markdown库的使用示例详解

《Python中Markdown库的使用示例详解》Markdown库是一个用于处理Markdown文本的Python工具,这篇文章主要为大家详细介绍了Markdown库的具体使用,感兴趣的... 目录一、背景二、什么是 Markdown 库三、如何安装这个库四、库函数使用方法1. markdown.mark

使用Navicat工具比对两个数据库所有表结构的差异案例详解

《使用Navicat工具比对两个数据库所有表结构的差异案例详解》:本文主要介绍如何使用Navicat工具对比两个数据库test_old和test_new,并生成相应的DDLSQL语句,以便将te... 目录概要案例一、如图两个数据库test_old和test_new进行比较:二、开始比较总结概要公司存在多

MySQL数据库函数之JSON_EXTRACT示例代码

《MySQL数据库函数之JSON_EXTRACT示例代码》:本文主要介绍MySQL数据库函数之JSON_EXTRACT的相关资料,JSON_EXTRACT()函数用于从JSON文档中提取值,支持对... 目录前言基本语法路径表达式示例示例 1: 提取简单值示例 2: 提取嵌套值示例 3: 提取数组中的值注意

CSS3中使用flex和grid实现等高元素布局的示例代码

《CSS3中使用flex和grid实现等高元素布局的示例代码》:本文主要介绍了使用CSS3中的Flexbox和Grid布局实现等高元素布局的方法,通过简单的两列实现、每行放置3列以及全部代码的展示,展示了这两种布局方式的实现细节和效果,详细内容请阅读本文,希望能对你有所帮助... 过往的实现方法是使用浮动加