16结构型模式-组合模式

我们很容易将“组合模式”和“组合关系”搞混。组合模式最初只是用于解决树形结构的场景,更多的是处理对象组织结构之间的问题。而组合关系则是通过将不同对象封装起来完成一个统一功能.

1 组合模式介绍

将对象组合成树形结构以表示整个部分的层次结构.组合模式可以让用户统一对待单个对象和对象的组合.
在这里插入图片描述
在这里插入图片描述

2 组合模式原理

在这里插入图片描述
在这里插入图片描述

3 组合模式实现

组合模式的关键在于定义一个抽象根节点类,它既可以代表叶子,又可以代表树枝节点,客户端就是针对该抽象类进行编程,不需要知道它到底表示的是叶子还是容器,可以对其进行统一处理.

树枝节点对象和抽象根节点类之间建立了一个聚合关联关系,在树枝节点对象中既可以包含叶子节点,还可以继续包含树枝节点,以此实现递归组合,形成一个树形结构.

/*** 抽象根节点角色* 对客户端而言,只需要针对抽象编程,无需关心具体子类是树枝节点还是叶子节点**/
public abstract class Component {public abstract  void add(Component c); //增加节点public abstract void remove(Component c); //删除节点public abstract Component getChild(int i); //获取节点public abstract void operation(); //业务方法
}
/*** 叶子节点* 叶子节点中不能包含子节点**/
public class Leaf extends Component {@Overridepublic void add(Component c) {}@Overridepublic void remove(Component c) {}@Overridepublic Component getChild(int i) {return null;}@Overridepublic void operation() {//叶子节点中的具体方法}
}
/*** 树枝节点* 树枝节点类是一个容器对象,它既可以包含树枝节点也可以包含叶子节点**/
public class Composite extends Component {//定义集合属性,保存子节点的数据private ArrayList<Component> list = new ArrayList<>();@Overridepublic void add(Component c) {list.add(c);}@Overridepublic void remove(Component c) {list.remove(c);}@Overridepublic Component getChild(int i) {return list.get(i);}//具体业务方法@Overridepublic void operation() {//在循环中,递归调用其他节点中的operation() 方法for (Component component : list) {component.operation();}}
}
4 组合模式应用实例

在这里插入图片描述
我们按照下图的表示,进行文件和文件夹的构建.
在这里插入图片描述
Entry类: 抽象类,用来定义File类和Directory类的共性内容

/*** Entry抽象类 (文件夹+文件)**/
public abstract class Entry {public abstract String getName(); //获取文件名public abstract int getSize(); //获取文件大小//添加文件或者文件夹方法public abstract Entry add(Entry entry);//显示指定目录下的所有文件的信息public abstract void printList(String prefix);@Overridepublic String toString() {return getName() +"(" + getSize() +")";}
}

File类,叶子节点,表示文件.

/*** File类,表示文件**/
public class File extends Entry{private String name; //文件名private int size; //文件大小public File(String name, int size) {this.name = name;this.size = size;}@Overridepublic String getName() {return this.name;}@Overridepublic int getSize() {return this.size;}@Overridepublic Entry add(Entry entry) {return null;}@Overridepublic void printList(String prefix) {System.out.println(prefix + "/" + this);}
}

Directory类,树枝节点,表示文件


/*** Directory 容器对象,表示文件夹**/
public class Directory extends Entry {//文件的名字private String name;//文件夹和文件的集合private ArrayList<Entry> directory = new ArrayList<>();public Directory(String name) {this.name = name;}@Overridepublic String getName() {return this.name;}/*** 获取文件大小*      1.如果entry对象是file类型,则调用getSize方法获取文件大小*      2.如果entry对象是Directory类型,会继续调用子文件夹的getSize()方法,形成递归调用*/@Overridepublic int getSize() {int size = 0;//遍历获取文件大小for (Entry entry : directory) {size += entry.getSize();}return size;}@Overridepublic Entry add(Entry entry) {directory.add(entry);return this;}@Overridepublic void printList(String prefix) {System.out.println("/" + this);for (Entry entry : directory) {entry.printList("/" + name);}}
}

测试

public class Client {public static void main(String[] args) {//创建根节点Directory rootDir = new Directory("root");//创建树枝节点Directory binDir = new Directory("bin");//向bin目录添加叶子节点binDir.add(new File("vi",10000));binDir.add(new File("test",20000));Directory tmpDir = new Directory("tmp");Directory usrDir = new Directory("usr");Directory mysqlDir = new Directory("mysql");mysqlDir.add(new File("my.cnf",30));mysqlDir.add(new File("test.db",25000));usrDir.add(mysqlDir);//将所有子文件夹封装到根节点rootDir.add(binDir);rootDir.add(tmpDir);rootDir.add(usrDir);rootDir.printList("");}
}
5 组合模式总结

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

toluaframework中C#怎么调用Lua的方法以及无GC方法

toluaframework中C#怎么调用Lua的方法 问题Util.CallMethodLuaManager.CallFunctionLuaFunction.LazyCall 解决方案LuaFunction脚本无GC消耗的调用 用法总结 问题 用过luaframework框架的人应该都知道框架提供了Util的工具类&#xff0c;工具类提供了一个方法就是Util.CallMet…

【SOPHON】算能盒子SE-16的C++模型转换

目录 ONNX转MLIR指定模型的预处理过程转换结果 本文以 arcface 为例, 介绍如何编译迁移一个onnx模型至TPU平台运行。 有疑问具体可参考 TPU-MLIR ONNX转MLIR 如果模型是图片输入, 在转模型之前我们需要了解模型的预处理。如果模型用预处理后的npz文件做输入, 则不需要考虑预处…

RabbitMQ初入门

1、RabbitMQ是什么 RabbitMQ是“实现了高级消息队列协议&#xff08;AMQP&#xff09;的开源消息代理软件&#xff08;亦称面向消息的中间件&#xff09;。RabbitMQ服务器是用Erlang语言编写的&#xff0c;而集群和故障转移是构建在开放电信平台框架上的。所有主要的编程语言均…

创纪录的1亿RPS DDoS攻击利用HTTP/2快速重置漏洞

导语&#xff1a;最近&#xff0c;一项创纪录的DDoS攻击引起了广泛关注。攻击者利用了HTTP/2协议中的一个快速重置漏洞&#xff0c;发起了一系列超大规模的攻击。本文将为大家详细介绍这次攻击的背景、影响以及应对措施。 攻击背景 最近&#xff0c;全球范围内遭受了一系列规模…

Java提升技术,进阶为高级开发和架构师的路线

原文网址&#xff1a;Java提升技术&#xff0c;进阶为高级开发和架构师的路线-CSDN博客 简介 Java怎样提升技术&#xff1f;怎样进阶为高级开发和架构师&#xff1f;本文介绍靠谱的成长路线。 首先点明&#xff0c;只写业务代码是无法成长技术的。提升技术的两个方法是&…

「林曦的亲子美育」讲讲关于阅读的那些事儿

「林曦的亲子美育」是“林曦的小世界”2023年策划的一档新栏目。林曦老师作为一个“小男生的妈妈”,在这些年分享了许多关于亲子教育的心得&#xff1a;以“美”作为连接和最高标准&#xff0c;会护持着小朋友的选择和人生。教育是一个生活的过程。做一餐饭、读一本书、看一张画…

网盘限速问题解析:哪家网盘真的不限速?

天下苦网盘限速久矣。市面上一些网盘工具要不然是收费限流&#xff0c;要不然是需要额外购买下载券。哪家网盘真的不限速&#xff1f; Zoho Workdrive 企业网盘是真正的不限速网盘&#xff0c;上传和下载文件都不限速&#xff0c;真正做到用户的网速有多快&#xff0c;下载就有…

YOLOv7优化:渐近特征金字塔网络(AFPN)| 助力小目标检测

💡💡💡本文改进:渐近特征金字塔网络(AFPN),解决多尺度削弱了非相邻 Level 的融合效果。 AFPN | 亲测在多个数据集能够实现涨点,尤其在小目标数据集。 收录: YOLOv7高阶自研专栏介绍: http://t.csdnimg.cn/tYI0c ✨✨✨前沿最新计算机顶会复现 🚀🚀🚀…

多线程---线程安全问题及解决

文章目录 一个线程不安全的案例造成线程不安全的原因抢占式执行多个线程修改同一个变量修改操作不是原子的内存可见性问题指令重排序问题 如何让线程变得安全&#xff1f;加锁volatile 一个线程不安全的案例 题目&#xff1a;有较短时间让变量count从0加到10_0000 解决方案&a…

myTracks for Mac:GPS轨迹记录器的强大与便捷

你是否曾经在户外活动或旅行中&#xff0c;希望能够记录下你的移动轨迹&#xff1f;或者在工作中&#xff0c;需要跟踪你的行程路线&#xff1f;myTracks for Mac 是一款强大的 GPS 轨迹记录器&#xff0c;它可以帮助你实现这些愿望。 myTracks 是一款专门为 Mac 设计的 GPS 轨…

[量化投资-学习笔记002]Python+TDengine从零开始搭建量化分析平台-MA均线的多种实现方式

MA 均线时最基本的技术指标&#xff0c;也是最简单&#xff0c;最不常用的&#xff08;通常使用EMA、SMA&#xff09;。 以下用两种不同的计算方法和两种不同的画图方法进行展示和说明。 MA 均线指标公式 MA (N)(C1 C2 C3 …C N )/N目录 方式一1.SQL 直接查询均值2.使用 pyp…

LLM系列 | 22 : Code Llama实战(下篇):本地部署、量化及GPT-4对比

引言 模型简介 依赖安装 模型inference 代码补全 4-bit版模型 代码填充 指令编码 Code Llama vs ChatGPT vs GPT4 小结 引言 青山隐隐水迢迢&#xff0c;秋尽江南草未凋。 小伙伴们好&#xff0c;我是《小窗幽记机器学习》的小编&#xff1a;卖热干面的小女孩。紧接…