Java设计模式-组合模式

简介

在软件设计中,设计模式是一种被广泛接受和应用的经验总结,旨在解决常见问题并提供可复用的解决方案。

组合模式是一种结构型设计模式,它允许将对象组合成树形结构以表示“部分-整体”的层次结构。这种模式能够使客户端以一致的方式处理单个对象和对象集合,将对象的组合与对象的使用具有一致性。

与其他设计模式的区别:

  1. 适配器模式 vs 组合模式:
    • 适配器模式主要用于将一个类的接口转换为客户端所期望的另一种接口,以解决接口不兼容的问题。
    • 组合模式则关注对象的组合形成树状结构,使客户端能够以一致的方式处理单个对象和对象集合。
  2. 装饰器模式 vs 组合模式:
    • 装饰器模式通过在不改变接口的情况下为对象动态添加功能,以提供更灵活的行为扩展。
    • 组合模式通过将对象组合成树形结构,表达对象之间的整体与部分关系,以统一对待单个对象和组合对象。

实现

下面是使用Java编程语言实现外观模式的示例代码:

// 抽象构件
interface Component {
    void operation();
}

// 叶子构件
class Leaf implements Component {
    public void operation() {
        // 执行叶子构件的操作
    }
}

// 容器构件
class Composite implements Component {
    private List<Component> components = new ArrayList<>();

    public void add(Component component) {
        components.add(component);
    }

    public void remove(Component component) {
        components.remove(component);
    }

    public void operation() {
        // 执行容器构件的操作
        for (Component component : components) {
            component.operation();
        }
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Component leaf1 = new Leaf();
        Component leaf2 = new Leaf();
        Component composite1 = new Composite();
        composite1.add(leaf1);
        composite1.add(leaf2);

        Component leaf3 = new Leaf();
        Component composite2 = new Composite();
        composite2.add(leaf3);
        composite2.add(composite1);

        composite2.operation();
    }
}

优缺点

优点

  1. 简化客户端代码:客户端无需区分处理单个对象还是对象集合,可以统一以相同的方式操作。
  2. 灵活性和扩展性:可以根据需求动态地增加、删除构件,而不影响现有代码结构。
  3. 符合开闭原则:添加新的构件类时,不需要修改现有代码,只需添加新的类即可。

缺点

  1. 设计复杂性:引入组合模式会增加类和对象的数量,增加了系统的复杂性。
  2. 限制构件类型:组合模式限制了构件的类型,只能通过抽象构件来统一处理。

运用场景

组合模式适用于以下场景:

  1. 当需求中存在部分与整体的层次关系,并且希望一致地对待单个对象和对象集合时。
  2. 当需要对对象以及对象的组合进行操作,并且希望客户端代码尽可能简化时。
  3. 当需要动态地增加、删除对象,并且希望系统具有良好的扩展性时。

总结

组合模式是一种在Java设计模式中常见且有用的模式。通过将对象组合成树形结构,它提供了一种处理对象集合的一致性方法,使客户端能够以相同的方式处理单个对象和对象集合。通过使用组合模式,我们可以简化客户端代码,提供灵活的扩展性,并遵循开闭原则。这种模式在具有部分与整体层次结构、需要一致处理对象和对象集合、以及需要动态增加、删除对象的场景中非常适用。

组合模式的实现可以使用Java编程语言。在代码中,我们定义了抽象构件接口,包括叶子构件和容器构件两种类型。叶子构件表示树形结构中的叶节点,而容器构件表示树形结构中的分支节点,可以包含其他构件。客户端代码可以通过调用容器构件的操作方法来递归地处理整个树形结构,无需关心单个对象和对象集合的差异。

组合模式有一些优点和缺点。优点包括简化客户端代码、提供灵活性和扩展性,以及符合开闭原则。然而,它也会增加系统的复杂性,并限制构件的类型。在实际应用中,我们应该根据具体需求和系统设计的目标来选择是否使用组合模式。

总之,组合模式在Java设计模式中具有重要的地位和应用价值。它通过统一处理单个对象和对象集合,简化了客户端代码,并提供了灵活的扩展性。了解和合理运用组合模式将有助于我们设计出更清晰、可扩展和易维护的软件系统。

本文转载于网络 如有侵权请联系删除

相关文章

  • 俄罗斯方块彩蛋(附星空表白彩蛋)

    俄罗斯方块?前言效果图展示俄罗斯方块游戏逻辑-第一步难度:⭐⭐-第二步难度:⭐⭐⭐1.方块实现逻辑:-第三步难度:⭐⭐-代码优化建议前言该文字主要讲解游戏逻辑代码实现,代码直接复制粘贴是无法直接运行的,直接运行可以在下文的传送门下载(0积分下载),下载好直接点击解决方案运行即可(需要按照要求安装easyx),或者去gitee查看源码,传送门在下文。更新时间:2022、5、18、16:11演示视频传送门:传送门源码见:gitee:传送门 0积分可直接下载:传送门 开发中途的启发:开发心得效果图展示游戏开始界面 游戏介绍页面: 游戏倒计时: 游戏界面 游戏失败: 彩蛋:星星是会动的 游戏BGM:歌名:SAD(ClapYourHands) 在线听 彩蛋BGM:Mistleoe 在线听 游戏过程全部BGM都在资源里了,包括倒计时,消行,彩蛋音乐,游戏音乐 俄罗斯方块游戏逻辑俄罗斯方块是在一块特定的长方形区域进行游戏运行,还有一个显示下一个方块的区域,得到的分数可以用一个变量贮存,然后在窗口打印出来,那么此时要完成这些基本游戏逻辑我们需要选择一个好的图形工具,可以画方块,可以画游戏区域和下一个

  • Linux文件操作高频使用命令

    大家好,又见面了,我是你们的朋友全栈君。文章目录0.新建操作:1.查看操作2.删除操作3.复制操作4.移动操作:5.重命名操作:6.解压压缩操作7.上传文件工具8.ln、file和touch命令9.查找操作命令:0.新建操作:mkdirabc#新建一个文件夹 touchabc.sh#新建一个文件 echo"abc">test.txt#新建一个文件,并将abc写入。这里用到了重定向符复制1.查看操作查看目录:ll#显示目录文件详细信息 du-h文件/目录#查看大小 pwd#显示路径复制查看文件内容: cat|head|tail命令 catabc.txt#查看abc的内容 head-5abc.txt#查看abc前5行内容。默认是10行 tail[选项]文件名 各选项的含义如下: +num:从第num行以后开始显示 -num:从距文件尾num行处开始显示。如果省略num参数,系统默认值为10. -f:循环读取,例如查看服务器日志时,可以实时观察 #filename文件里的最尾部的内容显示在屏幕上,并且不断刷新。 tail-ffilename #查看最后20行 ta

  • 框架安全之Spring渗透

    本篇文章是Spring渗透复现记录,记录了实际中常见的Spring漏洞并如何利用,及简单对漏洞底层的原理分析,分为四个部分:Spring简介、IDEA部署Spring、Vulhub靶场环境搭建和相关漏洞复现,在学习Spring中阅读了十几篇中英文相关文章,由浅入深地学习并最终成功复现了5个漏洞,参考的文章也在文中列出。此外,文中也可能会出现部分错误,望读者指出,谢谢。接着,开始我们的Spring渗透之路学习!!一、Spring简介1、Spring及其全家桶简介Spring框架是一个开放源代码的J2EE应用程序框架,是针对bean的生命周期进行管理的轻量级容器(lightweightcontainer)。Spring可以单独应用于构筑应用程序,也可以和Struts、Webwork、Tapestry等众多Web框架组合使用,并且可以与Swing等桌面应用程序AP组合。Spring框架主要由七部分组成,分别是SpringCore、SpringAOP、SpringORM、SpringDAO、SpringContext、SpringWeb和SpringWebMVCSpring全家桶包括5个关键部

  • golang学习笔记——异常

    自定义异常的两种方式packagemainimport("errors""fmt")funcmain(){//使用fmt.Errorferr1:=fmt.Errorf("%s","thisisnormalerror")fmt.Println(err1)//使用errorserr2:=errors.New("thisisanotparamerror")fmt.Println(err2)}应用 packagemainimport("errors""fmt")funcMyDiv(a,bint)(resultint,errerror){err=nilifb==0{err=errors.New("分母不能为0")}else{result=a/b}return}funcmain(){result,err:=MyDiv(6,0)iferr==nil{fmt.Println("result=",result)}else{fm

  • 技术分享和技术博客

    技术分享和技术博客上篇内容聊了一些技术社群相关的事情,本篇聊聊内外部技术分享、技术博客相关的事情。写在前面提到技术分享,一个绕不开的话题是为什么要做技术分享?你可能会得到许多不同的略带功利的答案,也可能会看到最朴素的:扎实自己技术的过程中帮助有相同需求的其他人。不论哪种动机,技术分享对于行业、公司、团队、个人都是好的事情。而技术分享的形式多种多样:除了各种形式会议、书籍、论文、课程外,和普通人相关度最高的,可能就是技术博客(文章)了吧。可以说,技术博客是距离普通技术人最近,能够解决不少麻烦的有效“手段”:项目遇到问题,可以通过搜索引擎找到在一些内外部博客中类似或者相同问题的解决过程及答案,或者对一些语焉不详的官方内容进行详尽补充的实战指南。在闲暇充电的过程,翻阅一些博客、专栏、公众号内容,可以开拓一些思路,了解行业里其他人做到什么程度。甚至可以结识在某些领域比当前自己更强的朋友,持续发展开始一些业务合作。但是当你挽起袖子,决定参考某个公司、团队、个人开启你自己的博客之路的时候,或许你会发现下面这个问题:不少优质的,“好”的技术博客内容都发生在前些年。前些年技术博客基本是技术人、技术团队

  • IT全栈-服务器03-X86-PCServer内存及NUMA介绍

    01PART知识回顾 本篇文章,我们重点介绍X86内存及NUMA相关知识。前期知识储备和回顾,请参考以下文章01)IT全栈-服务器01-X86-PCServer整机介绍02)IT全栈-服务器02-X86-PCServerCPU介绍02PARTX86内存参数 总结:DDR数字越大,频率越高,内存性能越好 03PARTCPU与内存互联架构 服务器的CPU和内存互联架构可以分三类:SMP:SymmetricMulti-ProcessorNUMA:Non-UniformMemoryAccessMPP:MassiveParallelProcessingA 单CPU 最早的服务器是1颗CPU;随着应用压力的增大,单颗CPU性能存在瓶颈;简单粗暴的办法---架构不变,再增加1颗CPU,即SMP。 B SMP 2颗CPU的SMP相比1颗CPU,CPU性能是增加了;但是由于2颗CPU共用内存总线,会存在内存总线的抢占和等待,导致不能完全发挥2颗CPU的性能;故需要架构改进,即NUMA。 C NUMA NUMA与SMP的区别:SMP多颗CPU共用内存总线,存在内存总线抢占情况,无法充分发挥CPU性能 NU

  • C++经典算法题-Shell 排序法 - 改良的插入排序

    34.AlgorithmGossip:Shell排序法-改良的插入排序说明插入排序法由未排序的后半部前端取出一个值,插入已排序前半部的适当位置,概念简单但速度不快。排序要加快的基本原则之一,是让后一次的排序进行时,尽量利用前一次排序后的结果,以加快排序的速度,Shell排序法即是基于此一概念来改良插入排序法。解法Shell排序法最初是D.LShell于1959所提出,假设要排序的元素有n个,则每次进行插入排序时并不是所有的元素同时进行时,而是取一段间隔。Shell首先将间隔设定为n/2,然后跳跃进行插入排序,再来将间隔n/4,跳跃进行排序动作,再来间隔设定为n/8、n/16,直到间隔为1之后的最后一次排序终止,由于上一次的排序动作都会将固定间隔内的元素排序好,所以当间隔越来越小时,某些元素位于正确位置的机率越高,因此最后几次的排序动作将可以大幅减低。举个例子来说,假设有一未排序的数字如右:8912659761812726198数字的总数共有10个,所以第一次我们将间隔设定为10/2=5,此时我们对间隔为5的数字进行排序,如下所示: 画线连结的部份表示要一起进行排序的部份,再来将间隔设

  • 【Python可视化5】Seaborn之线性回归

    Seaborn是基于matplotlib的Python可视化库。它提供了一个高级界面来绘制有吸引力的统计图形。Seaborn其实是在matplotlib的基础上进行了更高级的API封装,从而使得作图更加容易,不需要经过大量的调整就能使你的图变得精致。但应强调的是,应该把Seaborn视为matplotlib的补充,而不是替代物。 注:所有代码均在IPythonnotebook中实现lmplot(回归图)lmplot是用来绘制回归图的,通过lmplot我们可以直观地总览数据的内在关系先总览一下stripplot的API:seaborn.lmplot(x,y,data,hue=None,col=None,row=None,palette=None,col_wrap=None,size=5,aspect=1,markers='o',sharex=True,sharey=True,hue_order=None,col_order=None,row_order=None,legend=True,legend_out=True,x_estimator=None,x_bins=N

  • Geotools之“Hello World”——打开本地shp文件并显示

    概述:从本节开始,博文中会陆陆续续更新一些有关geotools相关的文章。本节讲述的是geotools的开胃菜,打开本地shp文件,并在窗口中显示。引言:geotools简介。Geotools是Java语言编写的开源GIS工具包。该项目已有十多年历史,生命力旺盛,代码非常丰富,包含多个开源GIS项目,并且基于标准的GIS接口。Geotools主要提供各种GIS算法,各种数据格式的读写和显示。在显示方面要差一些,只是用Swing实现了地图的简单查看和操作。但是用户可以根据Geotools提供的算法自己实现地图的可视化。OpenJump和udig就是基于Geotools的。Geotools用到的两个较重要的开源GIS工具包是JTS和GeoAPI。前者主要是实现各种GIS拓扑算法,也是基于GeoAPI的。但是由于两个工具包的GeoAPI分别采用不同的Java代码实现,所以在使用时需要相互转化。Geotools又根据两者定义了部分自己的GeoAPI,所以代码显得臃肿,有时容易混淆。由于GeoAPI进展缓慢,Geotools自己对其进行了扩充。另外,Geotools现在还只是基于2D图形的,缺乏

  • 你公司的大数据分析为何不成功?

    来源:哈佛商业评论(公众号:hbrchinese)作者迈克尔·施拉格(MichaelSchrage),美国麻省理工学院斯隆商学院电子商务研究中心的研究员。 【观点摘要】企业真正的挑战是洞察,利用大数据和分析法,以改善解决问题和决策的方式,会掩盖组织里一个现实情况,那就是新的分析法往往需要新的行为。 许多企业投下数百万美元用于大数据、分析法,并雇用数据分析家,但却感到很受挫。无可否认,他们现在得到了更多、更好的数据。他们的分析师和分析法也是一流的。但经理人对业务的想法和争论,似乎与过去的类型仍一样,只是他们使用的数据与分析法都比以前好得多。最终的决定可能是更加由数据驱动(data-driven),但组织文化给人的感觉仍然相同。正如一位CIO最近告诉我的,“我们现在可以做实时的分析,那是我在五年前根本无法想象的,但这么所带来的影响力,仍与我的预期差距很远。 怎么回事?我曾协助《财富》杂志1000大企业举办了几场大数据与分析法会议,并花费大量时间协助一些似乎对投资在分析法上的回报感到很满意的组织,结果一个明确的“数据启发法”(dataheuristic)出现了。分析成果为平庸到中等的企业,用

  • TensorFlow从1到2 | 第一章 消失的梯度

    上一主题《TensorFlow从0到1》介绍了人工神经网络的基本概念与其TensorFlow实现,主要基于浅层网络架构,即只包含一个隐藏层的全连接(FC,FullConnected)网络。新主题《TensorFlow从1到2》将探索近5年来取得巨大成功的深度神经网络(DeepNeuralNetworks),它已成为机器学习中一个独立的子领域——深度学习(DeepLearning)。本篇解释“深度”的含义,并引出在纵向扩展神经网络时所遇到的一个障碍——消失的梯度问题(VanishingGradientProblem)。VanishingGradientProblem,来源:https://www.youtube.com/watch?v=SKMpmAOUa2Q神秘的黑盒神经网络是一个“黑盒”(BlackBox)。不仅外行人看它如此,即使是对亲手构建它并训练它的工程师而言,亦是如此。它的神秘,并不在于打不开、看不到,而是学习过程不可控,识别原理不可解释。以一个全连接网络为例。当预设了它的架构,并对其进行初始化后,剩下的就是喂数据给它,至于网络中数以万计的权重和偏置如何调整,又将止步何处,整个

  • 【大咖说】英特尔首席工程师:大数据是上帝智能

    本文作者:吴甘沙全文3214字,建议阅读时间:5分钟上期回顾:【大咖说】吴军:数据为王和机器智能的时代一、大数据之道我认为把一件事情讲清楚,就要从这五个方面阐述:势、道、法、术、器。我今天主要从道、法、术三方面阐述大数据。2010年,谷歌每两天产生的数据量相当于人类文明曙光到2013年数以万计的时间长河所产生的数据总和,数据产生了指数级增长,我们可以看下指数曲线当中有一个有趣的特征:一开始的进展是非常缓慢的,但是突然到了一个转折点后,就以爆炸式的方式发展,下一步的进步可以是前面所有步的总和。因此,我们说,任何一个时间点的进步都不会太晚,而不是说机会都被前人拿走了。二、大数据为什么会产生指数级的增长?因为摩尔定律,一旦一个事情可以形成规律,就可以有预测能力,就有自我实现能力;摩尔定义不仅仅是技术的规律,也是经济的规律,如果两年以后你生产的东西和今天的东西一模一样,你的营业额会下降一半,因此,这意味着你必须得不停地奔跑,光跑得快,还不够,还得“更快”。人是大数据的第一推动力;我认为有三个特点:最小化信息不对称,消费者有选择权;交易成本趋向于零,消费者行为高频化,比如电商;覆盖长尾人群,更多

  • 基于springMVC拦截器实现操作日志统计

    1.spring配置文件配置。 <!--拦截器--> <mvc:interceptors> <!--日志拦截器--> <beanclass="cn.jeeweb.modules.common.interceptor.LogInterceptor"> <propertyname="openAccessLog"value="${openAccessLog}"/> </bean> <mvc:interceptor> <mvc:mappingpath="/**"/> <!--需排除拦截的地址--> <mvc:exclude-mappingpath="/static/**"/> <!--需排除拦截的地址--> <mvc:exclude-mappingpath="/upload/**"/>

  • Filter过滤器

    web.xml中元素执行的顺序listener->filter->struts拦截器->servlet。1.过滤器的概念Java中的Filter并不是一个标准的Servlet,它不能处理用户请求,也不能对客户端生成响应。主要用于对HttpServletRequest进行预处理,也可以对HttpServletResponse进行后处理,是个典型的处理链。优点:过滤链的好处是,执行过程中任何时候都可以打断,只要不执行chain.doFilter()就不会再执行后面的过滤器和请求的内容。而在实际使用时,就要特别注意过滤链的执行顺序问题2.过滤器的作用描述在HttpServletRequest到达Servlet之前,拦截客户的HttpServletRequest。 根据需要检查HttpServletRequest,也可以修改HttpServletRequest头和数据。 在HttpServletResponse到达客户端之前,拦截HttpServletResponse。 根据需要检查HttpServletResponse,可以修改HttpServletResponse头和数据

  • 闭关修炼180天 -- 手写SpringMVC框架(迷你版)

    SpringMvc知识须知 MVC设计模式 Model(模型):模型包含业务模型和数据模型,数据模型⽤于封装数据,业务模型⽤于处理业务。 View(视图):通常指的就是我们的jsp或者html。作⽤⼀般就是展示数据的。通常视图是依据模型数据创建的。 Controller(控制器):是应⽤程序中处理⽤户交互的部分。作⽤⼀般就是处理程序逻辑的。 springMvc请求执行流程 ⽤户发送请求⾄前端控制器DispatcherServlet DispatcherServlet收到请求调⽤HandlerMapping处理器映射器 处理器映射器根据请求Url找到具体的Handler(后端控制器),⽣成处理器对象及处理器拦截器(如果有则⽣成)⼀并返回DispatcherServlet DispatcherServlet调⽤HandlerAdapter处理器适配器去调⽤Handler 处理器适配器执⾏Handler Handler执⾏完成给处理器适配器返回ModelAndView 处理器适配器向前端控制器返回ModelAndView,ModelAndView是SpringMVC框架的⼀个底层对象,

  • 红黑树-想说爱你不容易

    前言:   记得在大一懵懵懂懂的时候就接触了红黑树的算法。但由于当时内功尚浅,无法将其内化,只是觉得它很神奇,是个好算法,设计它的人很牛!现今重拾起这个算法,不得不再次被它的精妙所折服!编写本文,是希望以鄙人的理解将红黑树算法的精髓向博客园的园友陈述一番,也希望对其有独特见解的朋友能不吝赐教。准备好了的话,我们就开始吧~ -------------------------------------------- PartI:BST   作为开始,我们得先谈谈二叉树(Binary Search Tree)。 1.假设存在一个如下简单的键值字符表: Key Value A 2 C 1 B 6 B 11 H 1 J 3   要求你按照读入顺序建立这样一棵二叉查找树,建好之后要求能够进行对于的查询操作。 源于二分查找的思想,二叉查找树有这样一个特点:   对于树上的任意一个结点,如果它有左右子结点的话,其结点大小必定大于其左子结点且小于其右子结点。   2.查找get(key)   由于

  • [UIDevice currentDevice].model

     iPhoneSimulator iPadSimulator iPodtouch iPad iPhone  

  • [ZJOI2019]语言

    https://www.luogu.org/problemnew/show/P5327 题解 首先考虑每个点能够到达的集合,它在树上一定是一个联通块。 先考虑枚举每个点,然后算它能到达多少点。 然后我们把所有跨越这个点的链全都拿出来,那么这个联通块的边数=这个点能够访问的点数=这些链的链并。 考虑传统的求链并的方法,就是按照\(dfs\)序排序,然后答案就是每个点的deep减去相邻两个点的\(lca\)的\(deep\)再减去所有点的\(lca\)的\(deep\)。 这就是大致思路,再考虑如何维护答案。 用类似树上差分的思想,对于每一条链,在\(u\)和\(v\)处分别打上\(u:+1\)和\(v:+1\)的标记,再在lca和\(fa[lca]\)处打上\(-1\)的标记。 然后用线段树合并维护所有标记的贡献即可。 代码 #include<bits/stdc++.h> #defineN100009 #defineinf2e9 #definelstr[cnt].l #definerstr[cnt].r usingnamespacestd; typedeflonglongll

  • 软件工程——团队作业1

    一.团队名字 软工练习生 二.队员的学号、姓名及博客链接 队长皮炜学号1600802022博客地址http://www.cnblogs.com/piwei/ 队员王银龙学号1600802025博客地址http://www.cnblogs.com/wylforever/ 队员魏仁杰学号1600802027博客地址http://www.cnblogs.com/Butterfly99/ 队员孟凡锚学号1600802020博客地址http://www.cnblogs.com/mengfanmao/ 三.团队项目描述 我们团队做的是一个关于颜色判断的益智类微信小程序 具体玩法就是,屏幕上会有两个框,左边的框会用带颜色的字体写上一个颜色 描述的词汇,例如用红色字体写绿色,右边的框也一样,例如用绿色字体写红 色,然后游戏要去就是判断左边描述的颜色是否和右边的字体颜色一样,正确 得分错误失分,达到一定分数到达下一关,每关有一定时间,如果没有在规定 时间到达下一关,则算失败。 灵感来源这个游戏(http://www.washing-colors.com/)不过模式更多,后期也 可能会根据进一步

  • 第一章 书面实验

    1.1OSI问题 请回答下述有关081模型的问题。(1)哪一层选择通信伙伴并判断其可用性、判断建立连接所需资掘的可用性、协调参与通信的应用程序,并就控制数据完整性和错误恢复的流程达成一致? 应用层(6)哪一层确保通过物理链路可靠地传输数据,且主要与物理地址、线路管理、网络拓扑、错误通知、按顺序传输帧以及流量控制有关? 数据链路层(8)哪一层提供逻辑地址,供路由器用来决定传输路径?  网络层(11)哪一层负责在网络中将来自不同应用程序的数据分开。 会话层        复习题(部分)                       作者:kali 出处:http://www.cnblogs.com/tqqnb/ ------------------------------------------- 个性签名:纸上学来终觉浅,绝知此事要躬行。 如果觉得这篇文章对你有小小的帮助的话,记得

  • MVC post model

    //type:"POST",//复杂对象传值用Post,//data:JSON.stringify({ids:List}),//JSON.stringify---must用来序列化//dataType:"json",//contentType:'application/json;charset=utf-8',//must

相关推荐

推荐阅读