当前位置: 首页 > web >正文

【设计模式-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.xdnf.cn/news/10785.html

相关文章:

  • 【208】VS2022 C++ 32位整数和unsigned char数组之间互相转换
  • 升级centos 7.9内核到 5.4.x
  • 更强劲,更高效:智源研究院开源轻量级超长视频理解模型Video-XL-2
  • ONLYOFFICE 与 LocalAI:在 Ubuntu 上搭建 AI 文档编辑环境
  • 法律大语言模型(Legal LLM)技术架构
  • 实验设计与分析(第6版,Montgomery著,傅珏生译) 第9章三水平和混合水平析因设计与分式析因设计9.5节思考题9.1 R语言解题
  • Stone 3D新版本发布,添加玩家控制和生物模拟等组件,增强路径编辑功能,优化材质编辑
  • 第3篇:数据库路由模块设计与 SQL 路由策略解析
  • 【IOS】GCD学习
  • centos中的ulimit命令
  • SpringCloud 分布式锁Redisson锁的重入性 高并发 获取锁
  • 「EN 18031」访问控制机制(ACM - 1):智能路由器的安全守卫
  • SuperMap GIS基础产品FAQ集锦(20250603)
  • 人工智能在智能教育中的创新应用与未来趋势
  • 人工智能AI之机器学习基石系列 第 3 篇:选择你的“学习方法”——初探监督学习与无监督学习
  • windows安装多个版本composer
  • 基于TI DSP控制的光伏逆变器最大功率跟踪mppt
  • go语言基础|slice入门
  • VR 虚拟仿真工器具:开启医学新视界的智慧钥匙​
  • 25年宁德时代新能源科技SHL 测评语言理解数字推理Verify题库
  • 基于Android的一周穿搭APP的设计与实现 _springboot+vue
  • Oracle、PostgreSQL 与 MySQL 数据库对比分析与实践指南
  • C++学习-入门到精通【13】标准库的容器和迭代器
  • NVIDIA DOCA 3.0:引领AI基础设施革命的引擎简析
  • Qwen3高效微调
  • k8s的出现解决了java并发编程胡问题了
  • [蓝桥杯]地址转换
  • 【ISAQB大纲解读】Kafka消息总线被视为“自下而上设计”?
  • 基于PostGIS的GeoTools执行原生SQL查询制图实践-以贵州省行政区划及地级市驻地为例
  • Python Pytest