【设计模式-3.7】结构型——组合模式

说明:本文介绍结构型设计模式之一的组合模式

定义

组合模式(Composite Pattern)又叫作整体-部分(Part-Whole)模式,它的宗旨是通过将单个对象(叶子节点)和组合对象(树枝节点)用相同的接口进行表示,使得客户对单个对象和组合对象的使用具有一致性,属于结构型设计模式。(引自《设计模式就该这样学》P263)

文件系统

以文件系统为例,如下,是服务器上某个文件夹的文件结构,该文件夹下既有文件夹,也有文件

在这里插入图片描述

如果我要构建这样一个文件夹-文件系统,代码应该是这样写的,如下:

(图片文件,ImageFile)

/*** 图片文件*/
public class ImageFile {/*** 图片名称*/private String name;public ImageFile(String name) {this.name = name;}/*** 展示*/public void show(int space) {for (int i = 0; i < space; i++) {System.out.print(" ");}System.out.println(name);}
}

(电影文件,MovieFile)

/*** 电影文件*/
public class MovieFile {/*** 电影名称*/private String name;public MovieFile(String name) {this.name = name;}/*** 展示*/public void show(int space) {for (int i = 0; i < space; i++) {System.out.print(" ");}System.out.println(name);}
}

(文件夹,Folder,定义多个文件集合,并开放对应的增加方法)

import java.util.ArrayList;/*** 文件夹*/
public class Folder {/*** 文件夹名称*/private String name;/*** 文件夹下的文件夹*/private ArrayList<Folder> folders = new ArrayList<>();/*** 文件夹下的图片文件*/private ArrayList<ImageFile> imageFiles = new ArrayList<>();/*** 文件夹下的视频文件*/private ArrayList<MovieFile> movieFiles = new ArrayList<>();public Folder(String name) {this.name = name;}/*** 添加文件夹*/public void addFolder(Folder folder) {folders.add(folder);}/*** 添加图片文件*/public void addImageFile(ImageFile imageFile) {imageFiles.add(imageFile);}/*** 添加电影文件*/public void addMoveFile(MovieFile movieFile) {movieFiles.add(movieFile);}/*** 展示*/public void show(int space) {// 打印文件夹space++;for (int i = 0; i < space; i++) {System.out.print(" ");}System.out.println(name);for (Folder folder : folders) {folder.show(space);}// 打印图片文件space++;for (ImageFile imageFile : imageFiles) {imageFile.show(space);}// 打印电影文件space++;for (MovieFile movieFile : movieFiles) {movieFile.show(space);}}
}

(客户端使用,Client)

public class Client {public static void main(String[] args) {// 顶级文件夹Folder folder = new Folder("folder");// 二级文件夹Folder images = new Folder("images");Folder movies = new Folder("movies");// 三级目录下的文件ImageFile boy = new ImageFile("boy.png");ImageFile girl = new ImageFile("girl.png");images.addImageFile(boy);images.addImageFile(girl);// 三级文件夹Folder director1 = new Folder("heizeming");Folder director2 = new Folder("xiaolinzhengshu");// 四级目录MovieFile movieFile1 = new MovieFile("luoshengmen.mp4");MovieFile movieFile2 = new MovieFile("qiwushi.mp4");director1.addMoveFile(movieFile1);director1.addMoveFile(movieFile2);MovieFile movieFile3 = new MovieFile("duomingjian.mp4");MovieFile movieFile4 = new MovieFile("qiefu.mp4");director2.addMoveFile(movieFile3);director2.addMoveFile(movieFile4);movies.addFolder(director1);movies.addFolder(director2);// 文件夹添加到顶级文件夹folder.addFolder(images);folder.addFolder(movies);folder.show(0);}
}

运行,hora!(看!),能实现目的

在这里插入图片描述

但这里存在问题,文件系统,简单来说只有文件夹和文件两个实体对象,代码中的图片文件、电影文件可以抽象为文件(File),这是整体与个体的场景。

组合模式

使用组合模式改进上述代码,如下:

(抽象节点类,Node)

/*** 抽象节点*/
public abstract class Node {/*** 节点名称*/protected String name;public Node(String name) {this.name = name;}/*** 添加节点*/protected abstract void add(Node node);/*** 展示*/protected void show(int space) {for (int i = 0; i < space; i++) {System.out.print(" ");}System.out.println(name);}/*** 重载方法,使用的时候就不用给参数了*/protected void show() {show(0);}
}

(文件夹,Folder)

import java.util.ArrayList;/*** 文件夹*/
public class Folder extends Node {/*** 文件夹下的子节点*/private ArrayList<Node> childrenNodes = new ArrayList<>();/*** 调用父类的构造方法*/public Folder(String name) {super(name);}@Overrideprotected void add(Node node) {childrenNodes.add(node);}@Overrideprotected void show(int space) {super.show(space);space++;for (Node node : childrenNodes) {node.show(space);}}
}

(文件,File)

/*** 文件*/
public class File extends Node {/*** 调用父类的构造方法*/public File(String name) {super(name);}@Overrideprotected void add(Node node) {System.out.println("不能添加子节点");}@Overrideprotected void show(int space) {super.show(space);}
}

(客户端使用,Client)

public class Client {public static void main(String[] args) {// 顶级文件夹Folder folder = new Folder("folder");// 二级文件夹Folder images = new Folder("images");Folder movies = new Folder("movies");// 三级目录下的文件File boy = new File("boy.png");File girl = new File("girl.png");images.add(boy);images.add(girl);// 三级文件夹Folder director1 = new Folder("heizeming");Folder director2 = new Folder("xiaolinzhengshu");// 四级目录File movieFile1 = new File("luoshengmen.mp4");File movieFile2 = new File("qiwushi.mp4");director1.add(movieFile1);director1.add(movieFile2);File movieFile3 = new File("duomingjian.mp4");File movieFile4 = new File("qiefu.mp4");director2.add(movieFile3);director2.add(movieFile4);movies.add(director1);movies.add(director2);// 文件夹添加到顶级文件夹folder.add(images);folder.add(movies);folder.show();}
}

执行如下,也实现了目的

在这里插入图片描述

这么看下来,文件系统场景使用组合模式实现是很不错的,代码少了很多,也削减了文件夹类中的职责(可以对比下Folder类前后的代码)

使用场景

在《设计模式就该这样学》(P229)这本书中,提到状态模式适用于以下场景:

(1)希望客户端可以忽略组合对象与单个对象的差异;

(2)对象层次具备整体和部分,呈树形结构;

除了文件系统、企业组织架构场景,我还没想到其他使用场景;

总结

本文介绍了结构型设计模式中的组合模式,参考《设计模式就该这样学》、《秒懂设计模式》、《设计模式的艺术》(第一版)这三本书,其中的例子来自《秒懂设计模式》。

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

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

相关文章

【TMS570LC4357】之相关驱动开发学习记录2

系列文章目录 【TMS570LC4357】之工程创建 【TMS570LC4357】之工程配置修改 【TMS570LC4357】之HALCOGEN使用 【TMS570LC4357】之相关问题及解决 【TMS570LC4357】之相关驱动开发学习记录1 ——————————————————— 前言 记录笔者在第一次使用TMS570过程中对…

3D Gaussian splatting 05: 代码阅读-训练整体流程

目录 3D Gaussian splatting 01: 环境搭建3D Gaussian splatting 02: 快速评估3D Gaussian splatting 03: 用户数据训练和结果查看3D Gaussian splatting 04: 代码阅读-提取相机位姿和稀疏点云3D Gaussian splatting 05: 代码阅读-训练整体流程3D Gaussian splatting 06: 代码…

【黑马程序员uniapp】项目配置、请求函数封装

黑马程序员前端项目uniapp小兔鲜儿微信小程序项目视频教程&#xff0c;基于Vue3TsPiniauni-app的最新组合技术栈开发的电商业务全流程_哔哩哔哩_bilibili 参考 有代码&#xff0c;还有app、h5页面、小程序的演示 小兔鲜儿-vue3ts-uniapp-一套代码多端部署: 小兔鲜儿-vue3ts-un…

前端使用 preview 插件预览docx文件

目录 前言一 引入插件二 JS 处理 前言 前端使用 preview 插件预览docx文件 一 引入插件 建议下载至本地&#xff0c;静态引入&#xff0c;核心的文件已打包&#xff08;前端使用 preview 插件预览docx文件&#xff09;&#xff0c;在文章目录处下载至本地&#xff0c;复制在项…

如何在运动中保护好半月板?

文章目录 引言I 半月板的作用稳定作用缓冲作用润滑作用II 在跳绳运动中保护好半月板III 半月板损伤自测IV 半月板“杀手”半月板损伤必须满足四个因素:消耗品引言 膝盖是连接大腿骨和小腿骨的地方,在两部分骨头的连接处,垫着两片半月形的纤维软骨板,这就是半月板。半月板分…

安科瑞防逆流方案落地内蒙古中高绿能光伏项目,筑牢北疆绿电安全防线

一、项目概况 内蒙古阿拉善中高绿能能源分布式光伏项目&#xff0c;位于内蒙古乌斯太镇&#xff0c;装机容量为7MW&#xff0c;采用自发自用、余电不上网模式。 用户配电站为35kV用户站&#xff0c;采用两路电源单母线分段系统。本项目共设置12台35/0.4kV变压器&#xff0c;在…

1.3 fs模块详解

fs 模块详解 Node.js 的 fs 模块提供了与文件系统交互的能力&#xff0c;是服务器端编程的核心模块之一。它支持同步、异步&#xff08;回调式&#xff09;和 Promise 三种 API 风格&#xff0c;可满足不同场景的需求。 1. 模块引入 const fs require(fs); // 回调…

LeetCode 70 爬楼梯(Java)

爬楼梯问题&#xff1a;动态规划与斐波那契的巧妙结合 问题描述 假设你正在爬楼梯&#xff0c;需要爬 n 阶才能到达楼顶。每次你可以爬 1 或 2 个台阶。求有多少种不同的方法可以爬到楼顶&#xff1f; 示例&#xff1a; n 2 → 输出 2&#xff08;1阶1阶 或 2阶&#xff0…

【学习分享】shell基础-参数传递

参数传递 我们可以在执行 Shell 脚本时&#xff0c;向脚本传递参数&#xff0c;脚本内获取参数的格式为 $n&#xff0c;n 代表一个数字&#xff0c;1 为执行脚本的第一个参数&#xff0c;2 为执行脚本的第二个参数。 例如可以使用 $1、$2 等来引用传递给脚本的参数&#xff0…

Fluence推出“Pointless计划”:五种方式参与RWA算力资产新时代

2025年6月1日&#xff0c;去中心化算力平台 Fluence 正式宣布启动“Pointless 计划”——这是其《Fluence Vision 2026》战略中四项核心举措之一&#xff0c;旨在通过贡献驱动的积分体系&#xff0c;激励更广泛的社区参与&#xff0c;为用户带来现实世界资产&#xff08;RWA&am…

Excel数据分析:基础

在现代办公环境中&#xff0c;Excel 是一款不可或缺的工具&#xff0c;它是 Microsoft&#xff08;微软&#xff09;开发的电子表格软件&#xff0c;用于处理和分析结构化数据。市场上还有其他类似的软件&#xff0c;如 Google Sheets 和 Apple Numbers&#xff0c;但 Excel 以…

12V降5V12A大功率WD5030A,充电器、便携式设备、网络及工业领域的理想选择

WD5030A 高效单片同步降压型直流 / 直流转换器 一、芯片核心概述 WD5030A 是一款高性能同步降压型 DC/DC 转换器&#xff0c;采用 平均电流模式控制架构&#xff08;带频率抖动功能&#xff09;&#xff0c;具备以下核心优势&#xff1a; 精准电流控制&#xff1a;快速响应负…

企业级AI迈入黄金时代,企业该如何向AI“蝶变”?

科技云报到原创。 近日&#xff0c;微软&#xff08;MSFT.US&#xff09;在最新全员大会上高调展示企业级AI业务进展&#xff0c;其中与巴克莱银行达成的10万份Copilot许可证交易成为焦点。 微软首席商务官贾德森阿尔索夫在会上披露&#xff0c;这家英国金融巨头已签约采购相…

Java编程课(一)

Java编程课 一、java简介二、Java基础语法2.1 环境搭建2.2 使用Intellij IDEA新建java项目2.3 Java运行介绍2.4 参数说明2.5 Java基础语法2.6 注释2.7 变量和常量一、java简介 Java是一种广泛使用的高级编程语言,最初由Sun Microsystems于1995年发布。它被设计为具有简单、可…

【Java Web】速通Tomcat

参考笔记:JavaWeb 速通Tomcat_tomcat部署java项目-CSDN博客 目录 一、Tomcat服务 1. 下载和安装 2. 启动Tomcat服务 3. 启动Tomcat服务的注意事项 4. 关闭Tomcat服务 二、Tomcat的目录结构 1. bin 🌟 2. conf 🌟 3. lib 4. logs 5. temp 6. webapps 7. work 三、Web项目…

Mysql 身份认证绕过漏洞 CVE-2012-2122

前言&#xff1a;CVE-2012-2122 是一个影响 MySQL 和 MariaDB 的身份验证漏洞&#xff0c;存在于特定版本中 vulhub/mysql/CVE-2012-2122/README.zh-cn.md at master vulhub/vulhubhttps://github.com/vulhub/vulhub/blob/master/mysql/CVE-2012-2122/README.zh-cn.md 任务一…

Win10停更,Win11不好用?现在Mac电脑比Win11电脑更便宜

最近不少朋友在换电脑前都犯了难。 以前大家最常说的一句是&#xff1a;“Mac太贵了&#xff0c;还是买Windows吧。”但现在不一样了&#xff0c;国补教育优惠下来&#xff0c;新款M4芯片的Mac mini的入门价已经降到了3000元左右&#xff0c;曾经的价格壁垒&#xff0c;已经不…

C#中Struct与IntPtr转换:实用扩展方法

C#中Struct与IntPtr转换&#xff1a;实用扩展方法 在 C# 编程的世界里&#xff0c;我们常常会遇到需要与非托管代码交互&#xff0c;或者进行一些底层内存操作的场景。这时&#xff0c;IntPtr类型就显得尤为重要&#xff0c;它可以表示一个指针或句柄&#xff0c;用来指向非托…

手机归属地查询接口如何用Java调用?

一、什么是手机归属地查询接口&#xff1f; 是一种便捷、高效的工具&#xff0c;操作简单&#xff0c;请求速度快。它不仅能够提高用户填写地址的效率&#xff0c;还能帮助企业更好地了解客户需求&#xff0c;制定个性化的营销策略&#xff0c;降低风险。随着移动互联网的发展…

43、视图解析-Thymeleaf初体验

43、视图解析-Thymeleaf初体验 “43、视图解析-Thymeleaf初体验”通常是指在学习Spring Boot框架时&#xff0c;关于如何使用Thymeleaf模板引擎进行视图解析的入门课程或章节。以下是对该主题的详细介绍&#xff1a; #### Thymeleaf简介 - **定义**&#xff1a;Thymeleaf是一个…