【设计模式深度剖析】【4】【结构型】【组合模式】| 以文件系统为例加深理解

👈️上一篇:适配器模式

设计模式深度剖析-专栏👈️

目 录

  • 组合模式
  • 定义
    • 英文原话
    • 直译
    • 如何理解?
  • 3个角色
    • UML类图
    • 代码示例
  • 组合模式的优点
  • 组合模式的使用场景
  • 示例解析:文件系统

组合模式

组合模式(Composite Pattern)也叫合成模式,用来描述部分与整体的关系。

  • 高层模块调用简单。一棵树形结构中的所有节点都是 Component,局部和整体对调用者来说没有任何区别,即高层模块不必关心自己处理的是单个对象还是整个组合结构**,**简化了高层模块的代码。
  • 节点自由增加。使用组合模式后,如果想增加一个树枝节点、树叶节点只需要找到其父节点即可。

当我们发现需求中是体现部分与整体层次的结构时,以及希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑用组合模式了。

定义

英文原话

Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

直译

将对象组合成树形结构来表示“部分-整体”的层次结构。组合模式使得客户端能够统一地处理单个对象和对象的组合。

如何理解?

叶子构件和容器构件实现了抽象构件,即实现了相同的接口,用户对单个对象和组合对象的使用具有一致性。

3个角色

UML类图

CompositePattern.png

组合模式(Composite Pattern)允许我们将对象组合成树形结构以表示“部分整体”的层次结构,使得客户端以统一的方式处理单个对象和对象的组合。以下是组合模式中的主要角色:

  1. 抽象构件(Component):它可以是接口或抽象类,为叶子和容器对象声明接口,在该接口中包含用于管理子对象的方法以及用于自身操作的方法。在组合模式中,抽象构件定义了叶子和容器构件的共同行为。
  2. 叶子构件(Leaf):叶子对象继承自抽象构件,它没有子节点,通常用于实现抽象构件中的业务方法。在组合结构中,叶子节点没有子节点,其实现了在抽象构件中定义的行为。
  3. 容器构件(Composite):容器对象也继承自抽象构件,并包含一组子构件。它实现了在抽象构件中定义的行为,并提供了添加、删除和访问其子对象的方法。容器构件可以包含其他容器或叶子,从而实现复杂的树形结构。
  4. 客户端(Client):通过抽象构件接口与组合结构进行交互。对于客户端而言,叶子对象和容器对象是一致的,客户端不需要区分它们。

代码示例

以下是一个简单的Java示例来说明组合模式:

// 抽象构件  
public interface Component {void operation();
}
// 叶子构件  
public class Leaf implements Component{@Overridepublic void operation() {// 业务处理逻辑System.out.println("leaf...");}
}
// 容器构件  
public class Composite implements Component {// 构件容器private ArrayList<Component> componentList = new ArrayList<>();// 添加构件public void add(Component component) {this.componentList.add(component);}// 删除构件public void remove(Component component) {this.componentList.remove(component);}// 获取子构件public ArrayList<Component> getChild() {return this.componentList;}@Overridepublic void operation() {// 业务逻辑System.out.println("branch...");}
}
// 客户端代码  
public class DemoTest {public static void main(String[] args) {// 创建一个根节点Composite root = new Composite();root.operation();// 创建树枝节点Composite branch = new Composite();// 创建叶子节点Leaf leaf = new Leaf();// 构建树形结构root.add(branch);branch.add(leaf);display(root);}// 遍历树(递归)public static void display(Composite root) {for (Component c : root.getChild()) {if(c instanceof Leaf){// 如果节点类型是叶子节点c.operation();}else{// 树枝节点c.operation();display((Composite) c);}}}
}
/* Output:
branch...
branch...
leaf...
*///~

在这个例子中,我们有一个Component接口,它定义了一个名为operation的方法。Leaf类实现了这个接口,并提供了具体的实现。Composite类同样实现了Component接口,并维护了一个子组件的列表。

组合模式的优点

  1. 高层模块调用简单。一棵树形机构中的所有节点都是 Component,局部和整体对调用者来说没有任何区别即高层模块不必关心自己处理的是单个对象还是整个组合结构,简化了高层模块的代码
  2. 节点自由增加。使用组合模式后,如果想增加一个树枝节点、树叶节点只需要找到其父节点即可。

组合模式的使用场景

使用组合模式的典型场景如下。

  1. 需要描述对象的部分和整体的等级结构,如树形菜单、文件和文件夹管理
  2. 需要客户端忽略个体构件和组合构件的区别,平等对待所有的构件

示例解析:文件系统

FileSystemDemo.png

在生活中,一个常见的组合模式的例子是文件系统。文件系统中的文件和文件夹可以看作是组合模式的实现,其中文件夹可以包含文件和其他文件夹(子文件夹),而文件则不包含任何子项。

以下是使用Java实现的示例,模拟了一个简单的文件系统:

// 抽象构件:文件或文件夹  
public interface FileSystemElement {  void display();  
}  
// 叶子构件:文件  
public class File implements FileSystemElement {  private String name;  public File(String name) {  this.name = name;  }  @Override  public void display() {  System.out.println("File: " + name);  }  
}  
// 容器构件:文件夹  
public class Folder implements FileSystemElement {  private String name;  private List<FileSystemElement> children = new ArrayList<>();  public Folder(String name) {  this.name = name;  }  public void add(FileSystemElement element) {  children.add(element);  }  public void remove(FileSystemElement element) {  children.remove(element);  }  @Override  public void display() {  System.out.println("Folder: " + name);  for (FileSystemElement child : children) {  child.display();  }  }  
}  
// 客户端代码
public class DemoTest {public static void main(String[] args) {// 创建文件夹和文件  Folder rootFolder = new Folder("root");Folder documentsFolder = new Folder("Documents");Folder picturesFolder = new Folder("Pictures");File file1 = new File("example.txt");File file2 = new File("image.jpg");// 将文件和文件夹添加到对应的父文件夹中  rootFolder.add(documentsFolder);rootFolder.add(picturesFolder);documentsFolder.add(file1);picturesFolder.add(file2);// 显示整个文件系统的结构  rootFolder.display();}
}/* Output:
Folder: root
Folder: Documents
File: example.txt
Folder: Pictures
File: image.jpg
*///~

在这个示例中,FileSystemElement是抽象构件接口,它声明了一个display方法用于显示文件或文件夹的信息。File类实现了这个接口,表示一个具体的文件。Folder类也实现了这个接口,表示一个文件夹,并且它有一个children列表来存储其子元素(文件和文件夹)。Folder类还提供了添加和删除子元素的方法。

DemoTest类的main方法中,我们创建了一个根文件夹rootFolder,并添加了documentsFolderpicturesFolder两个子文件夹。接着,我们向这两个文件夹中分别添加了一个文件和图片。最后,我们调用rootFolderdisplay方法来显示整个文件系统的结构。

这个输出展示了组合模式中的层次结构,其中文件夹可以包含文件和子文件夹,而文件则不包含任何子项。

👈️上一篇:适配器模式

设计模式深度剖析-专栏👈️

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/16665.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

多段图最短路径(动态规划法)

目录 前言 一、多段图的分析 二、算法思路 三、代码如下&#xff1a; 总结 前言 问题描述&#xff1a;设图G(V, E)是一个带权有向图&#xff0c;如果把顶点集合V划分成k个互不相交的子集Vi (2≤k≤n, 1≤i≤k)&#xff0c;使得对于E中的任何一条边(u, v)&#xff0c;必有u∈Vi&…

MSI U盘重装系统

MSI U盘重装系统 1. 准备一块U盘 首先需要将U盘格式化&#xff0c;这个格式化并不是在文件管理中将U盘里面的所有东西都删干净就可以了&#xff0c;需要在磁盘管理中&#xff0c;将这块U盘格式化&#xff0c;如果这块U盘有分区的话&#xff0c;那将所有的分区都格式化并且删除…

一个专为程序员设计的精致 Java 博客系统

大家好&#xff0c;我是 Java陈序员。 今天&#xff0c;给大家介绍一个设计精致的博客系统&#xff0c;基于 Java 实现&#xff01; 关注微信公众号&#xff1a;【Java陈序员】&#xff0c;获取开源项目分享、AI副业分享、超200本经典计算机电子书籍等。 项目介绍 bolo-solo …

【C++】二叉树进阶(二叉搜索树)

目录 一、内容安排说明二、 二叉搜索树2.1 二叉搜索树概念2.2 二叉搜索树操作2.2.1 二叉搜索树的查找2.2.2 二叉搜索树的插入2.2.3 二叉搜索树的删除 2.3 二叉搜索树的代码实现2.3.1 二叉搜索树的节点设置2.3.2 二叉搜索树类的框架2.3.3 二叉搜索树的查找函数2.3.3.1 非递归方式…

简单易懂的 API 集成测试方法

简介&#xff1a;API 集成测试的重要性 API 集成测试是一类测试活动&#xff0c;用于验证 API 是否满足功能性、可靠性、性能和安全性等方面的预期要求。在多 API 协作的应用程序中&#xff0c;这种测试尤为紧要。 在这一阶段&#xff0c;我们不仅审视单个组件&#xff0c;还…

【Qt窗口】—— 菜单栏

目录 &#xff08;一&#xff09;创建菜单栏 &#xff08;二&#xff09;在菜单栏中添加菜单 &#xff08;三&#xff09;创建菜单项 &#xff08;四&#xff09;在菜单项之间添加分割线 &#xff08;五&#xff09;综合示例 Qt 窗⼝是通过 QMainWindow类 来实现的。 QMa…

【NOIP2015普及组复赛】题3:求和

题3&#xff1a;求和 【题目描述】 一条狭长的纸带被均匀划分出了 n n n 个格子&#xff0c;格子编号从 1 1 1 到 n n n。每个格子上都染了一种颜色 c o l o r i color_i colori​ &#xff08;用 [ 1 &#xff0c; m ] [1&#xff0c;m] [1&#xff0c;m]当中的一个整数表…

前端如何学会全栈分页开发?源码和思路都在这了

本项目代码已开源&#xff0c;具体见&#xff1a; 前端工程&#xff1a;vue3-ts-blog-frontend 后端工程&#xff1a;express-blog-backend 数据库初始化脚本&#xff1a;关注公众号程序员白彬&#xff0c;回复关键字“博客数据库脚本”&#xff0c;即可获取。 前言 这是博客系…

GMSL2硬件设计V1.1

一、说明 GMSL(Gigabit Multimedia Serial Links),中文名称为千兆多媒体串行链路,是Maxim公司(现属于ADI)推出的一种高速串行接口,通过同轴电缆或屏蔽双绞线(STP)传输高速串行数据,用于汽车摄像头和显示器应用。GMSL2就是指ADI专有的第二代千兆多媒体串行链路技术,传输…

RPA+AI 应用案例集合:自动推流直播

使用场景&#xff1a; 自动定时推流直播 使用技术&#xff1a; python playwright 每个解决一个小问题 During handling of the above exception, another exception occurred:Traceback (most recent call last): File "D:\pythonTryEverything\putdonwphone\not_watch_…

前端开发工程师——webpack

一.环境准备 npm init -y npm i webpack webpack-cli -D 打包命令 npx webpack ./src/main.js --modedevelopment //development开发模式 //production生产模式 npx webpack 直接运行就行 二.加载器loader 在less/stylus/css/sass/images中添加适当的样式 例如&#xff1…

Python筑基之旅-文件(夹)操作和流

目录 一、文件操作 1、文件打开与关闭 2、文件读写 3、文件操作模式 4、文件编码 二、文件夹操作 1、创建文件夹 2、删除文件夹 3、改变当前工作目录 4、获取当前工作目录 5、检查文件/文件夹是否存在 6、遍历文件夹 三、文件路径操作 1、获取绝对路径 2、构建完…

爬山算法全解析:掌握优化技巧,攀登技术高峰!

一、引言 爬山算法是一种局部搜索算法&#xff0c;它基于当前解的邻域中进行搜索&#xff0c;通过比较当前解与邻域解的优劣来更新当前解&#xff0c;从而逐步逼近最优解。本文将对爬山算法进行详细的介绍。 二、爬山算法简介 爬山算法是一种基于贪心策略的优化算法&#xff…

如何利用Ubuntu服务器运行深度学习项目?

一、整体思路 先配置好服务器端的软件环境&#xff08;工程源码&#xff0c;miniconda&#xff0c;cuda&#xff0c;显卡驱动等&#xff09;&#xff0c;然后用自己电脑的pycharm远程连接服务器运行代码。一句话总结&#xff1a;借用服务器资源运行代码&#xff0c;本地pycharm…

ubuntu安装Stable Video Diffusion(SVD)让图片动起来

目录 写在前面 一、克隆或下载项目 二、下载预训练模型 三、创建环境 四、安装依赖 五、启动项目 六、解决报错 1.预训练模型下不来 2.TiffWriter.write() got an unexpected keyword argument fps 3.安装ffmpeg 4.No module named scripts 七、测试 写在前面 Stab…

深入解析内置模块OS:让你的Python代码更懂操作系统

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、OS模块简介与基础应用 二、文件与目录操作详解 三、OS模块的高级应用&#xff1a;双色…

web学习笔记(五十八)

目录 1. v-model 双向数据绑定 2. 事件修饰符 3. 路径别名 4. setup语法糖 4.1 语法糖的概念 4.2 setup语法糖 5. 配置代理服务器 1. v-model 双向数据绑定 v-model 双向数据绑定只能使用在表单标签&#xff1b; v-model双向数据绑定原理&#xff1a;采用 Object.de…

解决updateByExample时属性值异常的问题(部分属性值没有使用占位符?进行占位,而是变成了属性的名称)

目录 场景简介代码片断实体类 报错信息排查原因解决测试过程解决方案 场景简介 1、程序将mybatis框架升级为3.5.9版本后执行updateByExample方法时报错 代码片断 Condition condition new Condition(MbCcsSessionConfig.class); condition.createCriteria().andEqualTo(&quo…