详解组合模式

引言

        有一种情况,当一组对象具有“整体—部分”关系时,如果我们处理其中一个对象或对象组合(区别对待),就可能会出现牵一发而动全身的情况,造成代码复杂。这个时候,组合模式就是一种可以用一致的方式对待这个系统,让我们一起来看一下。

1.概念

        组合模式(Composite Patterm):组合多个对象形成树形结构以表示具有“整体—部分”关系的层次结构。组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性,组合模式又可以称为“整体—部分”(Part—Whole)模式,它是一种对象结构型模式。

        简单理解:整体—部分结构构建成树形结构,“部分”表示叶子结点,把叶子对象和容器对象中的方法(特殊的、公共的)都抽象出来形成抽象角色,然后针对抽象角色编程,即可实现“对象使用的一致性”这个核心思想。

2.模式结构

3.模式分析

        Component:抽象构件,可以是接口或抽象类,为叶子构件和容器构件对象声明接口,在该角色中可以包含所有子类共有行为的声明和实现。在抽象构件中定义了访问及管理它的子构件的方法,如增加子构件、删除子构件、获取子构件等。核心代码如下:

    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();//业务方法}

        Leaf:叶子构件,在组合结构中表示叶子节点对象,叶子节点没有子节点,它实现了在抽象构件中定义的行为。对于那些访问及管理子构件的方法,可以通过异常等方式进行处理。核心代码如下:   

 class Leaf extends Component {public void add(Component c){//异常处理或错误提示}public void remove(Component c) {//异常处理或错误提示}public Component getChild(int i) {//异常处理或错误提示return null;}public void operation() {//叶子构件具体业务方法的实现}}

        Composite:容器构件,在组合结构中表示容器节点对象,容器节点包含子节点,其子节点可以是叶子节点,也可以是容器节点,它提供一个集合用于存储子节点,实现了在抽象构件中定义的行为,包括那些访问及管理子构件的方法,在其业务方法中可以递归调用其子节点的业务方法。核心代码如下:   

 class Composite extends Component{private ArrayList<Component> children = new ArrayList<Component>();public void add(Component c) {list.add(c);}public void remove(Component c){list.remove(c);}public Component getChild(int i) {return (Component) list.get(i);}public void operation() {//容器构件具体业务方法的实现//递归调用成员构件的业务方法for (Object obj : children) {((Component) obj).operation();}}}

4.具体实例分析

        FileSystemComponent:抽象构件接口,定义了文件系统的叶子构件(文件)和容器构件(文件夹)的增删改查等方法,具体实例代码如下:

//抽象构件类:文件系统public interface FileSystemComponent {public void add(FileSystemComponent c);//增加成员public void remove(FileSystemComponent c);//删除成员public FileSystemComponent getChild(int i);//获取成员public void displayInfo();//显示文件信息}

        File:叶子构件,实现抽象构件FileSystemComponent接口,该类表示文件夹下的文件,具体实例代码如下:

//叶子构件public class File implements FileSystemComponent{private String name;public File(String name) {this.name = name;}public void add(FileSystemComponent c){System.out.println("叶子结点不支持此方法");}public void remove(FileSystemComponent c) {System.out.println("叶子结点不支持此方法");}public FileSystemComponent getChild(int i) {System.out.println("叶子结点不支持此方法");return null;}public void displayInfo() {System.out.println("File: " + name);}}

        Directory:容器构件,实现抽象构件FileSystemComponent接口,该类表示文件夹容器,如果想要查询文件夹下的各级文件夹(各级容器构件)或者文件(叶子构件),就需要递归的遍历文件夹,具体实例代码如下:

//容器构件public class Directory implements FileSystemComponent{private String name;private List<FileSystemComponent> list;public Directory(String name) {this.name = name;list = new ArrayList<>();}public void add(FileSystemComponent c) {list.add(c);}public void remove(FileSystemComponent c) {list.remove(c);}public FileSystemComponent getChild(int i) {return (FileSystemComponent) list.get(i);}public void displayInfo() {System.out.println("Directory: " + name + "/");for(FileSystemComponent fileSystemComponent : list){fileSystemComponent.displayInfo();}}}

        Client:客户端,依次创建文件夹和下面的文件,模拟文件系统。具体实例代码如下:

public class Client {public static void main(String[] args) {//创建文件File file1 = new File("Java.doc");File file2 = new File("数据结构.doc");//创建文件夹Directory directory = new Directory("学习资料");directory.add(file1);directory.add(file2);Directory rootDirectory = new Directory("D盘");rootDirectory.add(directory);//展示文件系统结构rootDirectory.displayInfo();}}

        运行程序,得到的结果如下:

5.优缺点

        主要优点如下:

        (1)组合模式可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,它让客户端忽略了层次的差异,方便对整个层次结构进行控制。

        (2)客户端可以一致地使用一个组合结构或其中单个对象,不必关心处理的是单个对象还是整个组合结构,简化了客户端代码。

        (3)在组合模式中增加新的容器构件和叶子构件都很方便,无须对现有类库进行任何修改,符合“开闭原则”。

        (4)组合模式为树形结构的面向对象实现提供了一种灵活的解决方案,通过叶子对象和容器对象的递归组合,可以形成复杂的树形结构,但对树形结构的控制却非常简单。

        主要缺点如下:

        (1)在增加新构件时很难对容器中的构件类型进行限制。有时候我们希望一个容器中只能有某些特定类型的对象,例如在某个文件夹中只能包含文本文件,使用组合模式时,不能依赖类型系统来施加这些约束,因为它们都来自于相同的抽象层,在这种情况下,必须通过在运行时进行类型检查来实现,这个实现过程较为复杂。

6.适用情况

        (1)在具有整体和部分的层次结构中,希望通过一种方式忽略整体与部分的差异,客户端可以一致地对待它们。

        (2)在一个使用面向对象语言开发的系统中需要处理一个树形结构。

        (3)在一个系统中能够分离出叶子对象和容器对象,而且它们的类型不固定,需要增加一些新的类型。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

计算机网络复习——概念强化作业

物理层负责网络通信的二进制传输 用于将MAC地址解析为IP地址的协议为RARP。 一个交换机接收到一帧,其目的地址在它的MAC地址表中查不到,交换机应该向除了来的端口外的所有其它端口转发。 关于ICMP协议,下面的论述中正确的是ICMP可传送IP通信过程中出现的错误信息。 在B类网络…

SQL语法——DQL查询

1.查询: 基础查询&#xff1a; select 列名1,列名2 from 表名; # 输入列名为*时为全查 条件查询&#xff1a; select 列名 from 表名 where 条件; #条件中含字符串时为字符串

Manus手套动作捕捉AI训练灵巧手

随着人工智能&#xff08;AI&#xff09;和机器人技术的融合日益紧密&#xff0c;使用真实动作数据AI扩容训练机器人的方式正在被用于开发更富表现力的机器人。Manus手套凭借精准的动作捕捉技术和导出数据的强大兼容性&#xff0c;在灵巧手的研发和应用中发挥了重要作用。 手部…

Altium Designer学习笔记 29 PCB布线_信号线

基于Altium Designer 23学习版&#xff0c;四层板智能小车PCB 更多AD学习笔记&#xff1a;Altium Designer学习笔记 1-5 工程创建_元件库创建Altium Designer学习笔记 6-10 异性元件库创建_原理图绘制Altium Designer学习笔记 11-15 原理图的封装 编译 检查 _PCB封装库的创建Al…

【02】复用松散型栅格切片

栅格切片分三种类型&#xff1a; 松散型、紧凑型v1紧凑型v2 见链接&#xff1a;https://blog.csdn.net/gislaozhang/article/details/144296963 说明&#xff1a;Linux环境或者Windows环境都可以参考类似的思路复用 前提条件&#xff1a;将旧服务切片服务缓存文件拷贝到新机器…

dd破坏asm磁盘头恢复---惜分飞

有朋友对asm disk的磁盘头dd了2048byte的数据 通过分析,gi软件版本,确认是11.2.0.4 Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production With the Real Application Clusters and Automatic Storage Management options. ORACLE_HOME /u01/app/…

【多线程-第一天-NSThread-互斥锁和自旋锁的区别-练习-异步下载网络图片 Objective-C语言】

一、互斥锁和自旋锁的区别 1.刚刚我们看过了,互斥锁和自旋锁,下边我们来看,互斥锁和自旋锁的一个区别, 1)互斥锁:如果发现其他线程正在执行锁定代码,线程会进入休眠(就绪状态),等其他线程时间片到了,打开锁后,线程会被唤醒(执行) 它是被唤醒的,相当于什么呢,…

【vue3 for beginner】Pinia基本用法:存储user的信息

&#x1f308;Don’t worry , just coding! 内耗与overthinking只会削弱你的精力&#xff0c;虚度你的光阴&#xff0c;每天迈出一小步&#xff0c;回头时发现已经走了很远。 &#x1f4d7;概念 Pinia 简介 Pinia 是一个用于 Vue.js 应用的状态管理库&#xff0c;是 Vuex 的…

PS的功能学习(钢笔+...)

钢笔工具 转换点工具&#xff0c;就是按住alt就可以转换了&#xff0c;也不用特意去工具列表里找着点 弯度钢笔工具也是比较鸡肋的&#xff0c;钢笔工具熟练之后&#xff0c;控制的也会更精确&#xff0c;弯度虽然简化了&#xff0c;但是也增加了曲线的弯度限制 其他的功能&a…

论著和教材的区别是什么?

1、内容性质 论著&#xff1a; 内容以作者的研究成果和学术观点为主。它是作者在某一学科领域进行深入研究后&#xff0c;通过实验、调查、理论推导等方式得出的创新性见解。例如&#xff0c;在生物学论著中&#xff0c;作者可能通过长期的野外观察和基因分析&#xff0c;提出…

java环境配置

后端JAVA软件的记录下载 纯粹自己懒&#xff0c;有个记录后面换电脑换公司方便 1、java的下载 oracle.com 更详细的可以看这个 JDK1.8下载、安装和环境配置教程_jdk1.8下载与安装教程_KristenX的博客-CSDN博客 2、java中变量的定义 数据类型 名称 值 /java中8中数据变量 …

03、Node.js安装及环境配置

1.下载node.js 下载地址&#xff1a;Node.js 2.安装 2.1 自定义安装路径&#xff08;可以选择默认&#xff09; 下图根据本身的需要进行&#xff0c;我选择了默认Node.js runtime&#xff0c;然后Next&#xff1a; Node.js runtime &#xff1a;表示运行环境 npm package mana…

如何突破TikTok播放量零瓶颈

TikTok已成为全球最受欢迎的短视频平台之一&#xff0c;吸引了数亿用户。然而&#xff0c;许多新手创作者在上传视频后常常面临播放量为零的困境。这种情况让人感到困惑&#xff0c;尤其是在精心制作视频内容后&#xff0c;却没有得到预期的曝光和互动。那么&#xff0c;为什么…

基于SpringBoot+Vue框架的在线考试系统的设计与实现

基于SpringBootVue框架的在线考试系统的设计与实现 系统合集跳转 源码获取链接 一、系统环境 运行环境: 最好是java jdk 1.8&#xff0c;我们在这个平台上运行的。其他版本理论上也可以。 IDE环境&#xff1a; Eclipse,Myeclipse,IDEA或者Spring Tool Suite都可以 tomcat环…

楼房销售系统设计与实现

文末获取源码和万字论文&#xff0c;制作不易&#xff0c;感谢点赞支持。 毕 业 设 计&#xff08;论 文&#xff09; 题目&#xff1a;楼房销售系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xf…

King’s Biobank 生物样本库管理系统:高效、智能的样本管理解决方案

近年来&#xff0c;生物样本资源已成为生物医药产业和国家生物安全战略的核心基石&#xff0c;在病因研究、临床诊疗及疾病预防等多个关键领域发挥着不可替代的作用。然而&#xff0c;科研机构、检测中心和医院在样本管理方面普遍面临以下挑战&#xff1a; 重复记录&#xff0c…

spring下的beanutils.copyProperties实现深拷贝

spring下的beanutils.copyProperties方法是深拷贝还是浅拷贝&#xff1f;可以实现深拷贝吗&#xff1f; 答案&#xff1a;浅拷贝。 一、浅拷贝深拷贝的理解 简单说拷贝就是将一个类中的属性拷贝到另一个中&#xff0c;对于BeanUtils.copyProperties来说&#xff0c;你必须保…

Linux---对缓冲区的简单理解--第一个系统程序

前序&#xff1a; 首先先理解一下什么是回车与换行&#xff1b;回车和换行是两个概念&#xff0c;它们不是一个东西&#xff1b; 回车:光标回到开始&#xff1b;换行:换到下一行&#xff1b; 如下图&#xff1a; 行缓冲区 如何理解缓冲区问题&#xff1f; 可以认为&#xff0…

『RabbitMQ』 windows下 安装RabbitMQ 并在Python中使用测试

目录 1. 安装ERLANG2. 安装RabbitMQ3. 新建用户Python的测试代码 生产者和消费者总结欢迎关注 『RabbitMQ』 专栏,持续更新中 欢迎关注 『RabbitMQ』 专栏,持续更新中 1. 安装ERLANG 下载之前先看兼容性,这里我打算下载26.1版本的Erlang以适配RabbitMQ cloud.emqx.com/cons…

【教程】创建NVIDIA Docker共享使用主机的GPU

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 这套是我跑完整理的。直接上干货&#xff0c;复制粘贴即可&#xff01; # 先安装toolkit sudo apt-get update sudo apt-get install -y ca-certifica…