设计模式之组合模式(Composite)

一、组合模式介绍

       组合模式(Composite Pattern) 的定义是:将对象组合成树形结构以表示整个部分的层

       次结构。组合模式可以让用户统一对待单个对象和对象的组合。

       如在windows操作系统中的目录结构,其实就是树形目录结构,可以通过 tree /f 命令

       将目录实现树形结构展示,如下图所示:

              

       在上图中包含了文件夹和文件两类不同元素,其中在文件夹中可以包含文件,还可以继续

       包含子文件夹。子文件夹中可以放入文件,也可以放入子文件夹。文件夹形成了一种容器

       结构(树形结构),递归结构。如下图所示:

               

       接着我们再来思考虽然文件夹和文件是不同类型的对象,但是他们有一个共性,

       就是都可以被放入文件夹中。 其实文件和文件夹可以被当做是同一种对象看待。

       组合模式其实就是将一组对象(文件夹和文件)组织成树形结构,以表示一种“部分-整体”

       的层次结构,(目录与子目录的嵌套结构)。组合模式让客户端可以统一单个对象(文件)

       和组合对象(文件夹)的处理逻辑(递归遍历)。

       组合模式更像是一种数据结构和算法的抽象,其中数据可以表示成树这种数据结构,

       业务需求可以通过在树上的递归遍历算法来实现。

       我们很容易将“组合模式”和“组合关系”搞混。组合模式最初只是用于解决树形结构的场景,

       更多的是处理对象组织结构之间的问题。而组合关系则是通过将不同对象封装起来完成一

       个统一功能。

二、组合模式原理

        组合模式结构图如下:

                

        组合模式主要包括三种角色,即:

                1)抽象根节点(Component):定义系统各层次对象的共有方法和属性,可以预先

                      定义一些默认行为和属性。

                     在该角色中可以包含所有子类共有行为的声明和实现。在抽象根节点中定义了访问

                     及管理它的子构件的方法,如增加子节点、删除子节点、获取子节点等。

                2)树枝节点(Composite):定义树枝节点的行为,存储子节点,组合树枝节点和

                     叶子节点形成一个树形结构,树枝节点也可以称之为“容器节点或容器对象”。

                     树枝节点可以包含树枝节点,也可以包含叶子节点,它其中有一个集合可以用于存储

                     子节点,实现了在抽象根节点中定义的行为。包括那些访问及管理子构件的方法,在

                      其业务方法中可以递归调用其子节点的业务方法。

                3)叶子节点(Leaf):叶子节点对象,其下再无分支,是系统层次遍历的最小单位。

                      在组合模式中叶子节点没有子节点,它实现了在抽象根节点中定义的行为。

       组合模式用代码表示,代码如下:   

/******************************************************** 抽象根节点* 对客户端而言,只需要针对抽象编程,无需关心具体子类实现* 抽象根节点可以是抽象类或接口** @author lbf*******************************************************/
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();
}/******************************************************** 树枝节点* 容器对象,即可以包含子节点,也可以包含叶子节点** @author lbf*******************************************************/
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 (Component) list.get(i);}@Overridepublic void operation() {//在树枝节点中的业务方法,将递归调用其他节点中的operation() 方法for (Component component : list) {component.operation();}}
}/******************************************************** 叶子节点* 叶子节点不能包含具体子节点* * @author lbf********************************************************/
public class Leaf extends Component{@Overridepublic void add(Component c) {//具体操作}@Overridepublic void remove(Component c) {//具体操作}@Overridepublic Component getChild(int i) {//具体操作return new Leaf();}@Overridepublic void operation() {//叶子节点具体业务方法}}

三、组合模式应用示例

       以列出某一目录下所有的文件和文件夹为例来看下组合模式的使用,

       实现类图如下:

               

       示例代码:

/******************************************************** 以列出某一目录下所有的文件和文件夹为例来看下组合模式的使用* Entry--抽象类** @author lbf*******************************************************/
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() + ")";}
}/******************************************************** 文件类* 叶子节点** @author lbf*******************************************************/
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 name;}@Overridepublic int getSize() {return size;}@Overridepublic Entry add(Entry entry) {return null;}@Overridepublic void printList(String prefix) {System.out.println(prefix + "/" + this);}
}/******************************************************** 文件夹类* 树枝节点** @author lbf*******************************************************/
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 Test {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(mysqlDir);rootDir.printList("");}
}

       

四、组合模式总结

1、组合模式分类

      1)透明组合模式

            透明组合模式中,抽象根节点角色中声明了所有用于管理成员对象的方法,比如在示

            例中 `Component` 声明了 `add`、`remove` 、`getChild` 方法,这样做的好处是确保

            所有的构件类都有相同的接口。透明组合模式也是组合模式的标准形式。

            透明组合模式的缺点是不够安全,因为叶子对象和容器对象在本质上是有区别的,叶

           子对象不可能有下一个层次的对象,即不可能包含成员对象,因此为其提供 add()、

           remove() 等方法是没有意义的,这在编译阶段不会出错,但在运行阶段如果调用这些

           方法可能会出错(如果没有提供相应的错误处理代码)

           透明组合模式结构图如下:

                   

      2)安全组合模式

            在安全组合模式中,在抽象构件角色中没有声明任何用于管理成员对象的方法,而是

            在树枝节点类中声明并实现这些方法。安全组合模式的缺点是不够透明,因为叶子构件

            和容器构件具有不同的方法,且容器构件中那些用于管理成员对象的方法没有在抽象构件

            类中定义,因此客户端不能完全针对抽象编程,必须有区别地对待叶子构件和容器构件。

            安全组合模式结构图如下:

                    

2、组合模式优点

      1)组合模式可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,它让客户端

            忽略了层次的差异,方便对整个层次结构进行控制。

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

            整个组合结构,简化了客户端代码。

      3)在组合模式中增加新的树枝节点和叶子节点都很方便,无须对现有类库进行任何修改,

            符合“开闭原则”。

      4)组合模式为树形结构的面向对象实现提供了一种灵活的解决方案,通过叶子节点和树枝

            节点的递归组合,可以形成复杂的树形结构,但对树形结构的控制却非常简单。

3、组合模式缺点

      1)使用组合模式的前提在于,你的业务场景必须能够表示成树形结构。

            所以,组合模式的应用场景也 比较局限,它并不是一种很常用的设计模式。

4、组合模式适用场景

      1)处理一个树形结构,比如,公司人员组织架构、订单信息等;

      2)跨越多个层次结构聚合数据,比如,统计文件夹下文件总数;

      3)统一处理一个结构中的多个对象,比如,遍历文件夹下所有 XML 类型文件内容。

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

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

相关文章

加速“人工智能+”落地,青云如何打磨智算基石

智算中心建设不断加速&#xff0c;正成为推动数字经济发展的新引擎。 根据天风证券的研究&#xff0c;2024年1-6月&#xff0c;全国智算中心招投标相关事件791起&#xff0c;较上年同期增加407.1%。 围绕AI算力&#xff0c;云计算厂商也在积极探索第二增长曲线。根据2024年半年…

2024.10月17日- Vue.js(2)

2.4 计算属性 从字符串反转中&#xff0c;我们发现 插值语法的初衷是用于简单运算。明显练习题中的写法&#xff0c;违背了插值语法的初衷。 methods方法可以。但是方法中如果封装的是性能开销比较大的逻辑代码&#xff0c;需要进行大量的运算&#xff0c;并且别的属性还依赖…

【数据结构与算法】栈和队列

文章目录 一.栈1.1定义 顺序栈和链式栈1.2基本操作1.2.1表示1.2.2初始化1.2.3清空1.2.4销毁1.2.5入栈1.2.6出栈1.2.7取栈顶 1.3共享栈1.3.1定义1.3.2进栈出栈 二.队列2.1定义 顺序队列和链式队列循环队列2.2基本操作2.2.1初始化2.2.2判空2.2.3求队列长度2.2.4取队头元素2.2.5销…

Python123练习题

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;题目解析 目录 &#x1f449;&#x1f3fb;百钱买百鸡&#x1f449;&#x1f3fb;鸡兔同笼&#x1f449;&#x1f3fb;最大公约数和最小公倍数&#x1f449;…

redux与react18setState触发render问题

最近在做一个需求&#xff0c;需要用im做那个协同。 刚好遇到一个比较有意思的问题。 具体问题就不赘述了。 根本原因就是在修改state的时候&#xff0c;触发了两次重渲染。 后面也是做了一些验证 demo function App() {const [state, setState] useState("");con…

JDK、JRE、JVM相关知识点

1、JDK、JRE、JVM三者的关系 JDK‌&#xff1a;Java开发工具包&#xff0c;包括编译工具&#xff08;javac.exe&#xff09;、打包工具&#xff08;jar.exe&#xff09;等&#xff0c;也包含JRE。JDK是开发Java程序的主要工具包&#xff0c;包括了Java运行环境、Java工具和Jav…

C++之设计原则

在C中&#xff0c;设计原则是一套指导软件开发过程中决策和设计模式的准则&#xff0c;旨在提高软件的可维护性、可扩展性、灵活性和可靠性。 以下是几种核心设计原则&#xff1a; 1.单一职责 功能单一&#xff0c;方便组合和复用。 图示&#xff1a; 应用场景&#xff1a;…

【2024CANN训练营第二季】Ascend C概述

什么是算子 算子在神经网络中的定义 算子对应网络中层或者节点的计算逻辑 算子的数学含义 算子在数学中的定义&#xff1a; 一个函数空间到函数空间上的映射O&#xff1a;X->X&#xff1b; 广义&#xff1a; 对任何函数进行某一项操作都可以认为是一个算子。比如微分算…

redis IO多路复用机制

目录 一、五种 I/O 模型 1.阻塞IO&#xff08;Blocking IO&#xff09; 2.非阻塞IO&#xff08;Nonblocking IO&#xff09; 3.IO多路复用&#xff08;IO Multiplexing&#xff09; 通知的方式 select模式 poll模式 epoll模式 4.信号驱动IO&#xff08;Signal Driven …

SD-WAN技术的特点和应用场景

近年来&#xff0c;SD-WAN逐渐成为企业网络建设中的热门技术。那么&#xff0c;SD-WAN到底是什么呢&#xff1f;简而言之&#xff0c;SD-WAN&#xff08;软件定义广域网&#xff09;结合了软件定义网络&#xff08;SDN&#xff09;与广域网优化技术&#xff0c;为企业提供了更加…

一文读懂:Session、Cookie与Token

我是小白刚刚接触JWT&#xff0c;看了b站一些相关视频、查了中国知网和csdn其他人的文章之后&#xff0c;总结出了这篇文章。写文章的初心是为了检验自己是否透彻了解了知识点以及之后复习。如果标题党了&#xff0c;斯米马赛请原谅&#xff01;&#xff01;&#xff01;欢迎大…

企业AI助理与知识库管理系统:重塑企业知识管理的新篇章

在数字化转型的浪潮中&#xff0c;企业正面临着前所未有的机遇与挑战。如何高效管理、快速获取并利用企业内部的知识资源&#xff0c;成为了提升企业竞争力的关键。近年来&#xff0c;企业AI助理与知识库管理系统的结合&#xff0c;正逐步成为企业知识管理的新趋势&#xff0c;…

【C语言】循环嵌套:乘法表

循环嵌套&#xff0c;外层循环执行一次&#xff0c;内层循环执行i次。分别控制 在循环的过程中加一层循环。 多层循环属于循环嵌套、嵌套循环 #include <stdio.h> #include <math.h> /* 功能&#xff1a;循环嵌套 乘法表 时间&#xff1a;2024年10月 地点&#xf…

老机MicroServer Gen8再玩 OCP万兆光口+IT直通

手上有一台放了很久的GEN8微型服务器&#xff0c;放了很多年&#xff0c;具体什么时候买的我居然已经记不清了 只记得开始装修的时候搬家出去就没用了&#xff0c;结果搬出去有了第1个孩子&#xff0c;孩子小的时候也没时间折腾&#xff0c;等孩子大一点的时候&#xff0c;又有…

使用Python PyQt5 vscode 制作流水灯或者交通灯

需要用到 Python PyQt5 vscode&#xff0c;其他的各模块引用在代码里面有&#xff0c;自己找找就行 制作流水灯代码 import sys from PyQt5.QtCore import (QEvent, QTimer, Qt,QPoint) from PyQt5.QtWidgets import (QApplication, QMenu,QMainWindow) from PyQt5.QtGui imp…

限时设计ui

ctrl-------放大缩小 空格-----画面移动 alt------复制 页面<画板<图层 添加交互事件 原型 点击蓝色的圆&#xff0c;从1跳转到2 点击绿色的圆&#xff0c;从2跳转到1

如何实现安川MP3300运动控制器与西门子1200系列PLC进行ModbusTCP通讯

在工业自动化中&#xff0c;实现不同品牌、不同型号设备之间的通讯是确保生产流程顺畅、高效运行的关键。本文详细介绍了安川MP3300运动控制器与西门子1200系列PLC进行ModbusTCP通讯的具体方法。 一&#xff0e;软硬件需求 1.一台安川MP3300CPU301&#xff0c;其IP地址是192.…

类和对象的认识

类&#xff1a;类是用来描述一个对象的&#xff0c;在java中万物皆对象&#xff0c;通过对类的抽象&#xff0c;类有哪些属性和行为&#xff0c;将这些抽象出来就是类。比如&#xff1a;狗&#xff0c;有名字&#xff0c;年龄&#xff0c;要吃饭的行为等等&#xff0c;将这些动…

ssh连接慢的问题或zookeeper远程连接服务超时

问题原因&#xff1a; 在SSH登录过程中&#xff0c;服务器会通过反向DNS查找客户端的主机名&#xff0c;然后与登录的IP地址进行匹配&#xff0c;以验证登录的合法性。如果客户端的IP没有域名或DNS服务器响应缓慢&#xff0c;这可能导致SSH登录过慢。为了解决这个问题&#xf…

【无处躲藏的图片】和【时隐时现的图片】

文章目录 一、效果二、源码1. pom依赖2. 核心源码13. 核心源码2 一、效果 二、源码 1. pom依赖 <dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.9</version></dependency…