小侃设计模式(九)-组合模式

news2025/4/19 12:42:44

1.概述

组合模式(Composite Pattern)又叫部分整体模式,它创建了对象组的树形结构,将对象组合成树状结构以表示“整体-部分”的层析关系,使用户对单个对象和组合对象具有一致的访问性,是结构型设计模式的一种。本文将分析组合模式的原理及使用方式。

2.原理及使用

2.1 原理

组合模式一般用来描述整体与部分的关系,它将对象组织到树形结构中,以树的管理方式来管理对象。顶层的节点被称为根节点,根节点下包含树枝节点和叶子节点,树枝节点下面可以包含树枝节点和叶子节点。这个模式与二叉树的模式类似,树形结构图如下:
在这里插入图片描述
根节点和树枝节点本质上是同一种数据类型,都可以作为存储子类的容器;叶子节点与树枝节点有所区别,叶子节点不具备存储子类的功能。但是在组合模式中,树枝节点和叶子节点会被看作同一种书籍类型(为了统一抽象和定义,让树枝节点和叶子节点具备统一行为)。
因此,在组合模式中,整个树形结构中的对象都是同一种类型,具备相同的行为,操作时不需要区分节点,效率较高。
组合模式类图如下:
在这里插入图片描述
组合模式主要包含以下三个角色:

抽象构件角色(Component):为树叶构件和树枝构件声明公共接口,它可以是接口或者抽象类,可以实现一些默认行为;
树枝构件角色(Composite):是组合中的分支节点对象,它有子节点,用于继承和实现抽象构件,负责管理字节点;
树叶构件角色(Leaf):是组合中的叶节点对象,它没有子节点,用于继承或实现抽象构件。

组合模式可以分为透明式组合模式和安全式组合模式,它们之间的区别在于:透明式的组合模式在抽象构件角色(Component)中声明访问和管理子类的接口;安全式的组合模式在抽象构件角色中不声明管理子类接口,管理工作由树枝构件自己完成。上述类图主要是透明式组合模式。

2.2 案例

有一个学校,展现出学校下的各个组织。学校下面有学院,学院下面有不同的专业。不同的组织可以对其下属组织进行新增、裁撤等。

分析:首先需要定义一个抽象构件角色(OrganizationComponent)来实现一些组织的基础操作,比如:add()、delete()、getChildren()等;学校下面的学校(University)、学院(College)可以作为一个树枝构件角色,学校的子节点是学院,学院的子节点是专业(Profession);专业(Profession)在这里属于叶子节点(实际中还可能有班级这类的子组织,这里不做考虑了)。

由上述分析可得出案例的类图如下:
在这里插入图片描述

编码如下:

//抽象组件
public abstract class UniversityComponent {

    public String name;

    public String description;

    public UniversityComponent(String name, String description) {
        this.name = name;
        this.description = description;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    protected void add(UniversityComponent universityComponent) {
        throw new UnsupportedOperationException();
    }

    protected void remove(UniversityComponent universityComponent) {
        throw new UnsupportedOperationException();
    }

    protected List<UniversityComponent> getChildern() {
        throw new UnsupportedOperationException();
    }

    protected abstract void operation();
}

//学校树枝构件
@Slf4j
public class University extends UniversityComponent {

    private List<UniversityComponent> lists = new ArrayList<>();

    public University(String name, String description) {
        super(name, description);
    }

    @Override
    protected void add(UniversityComponent universityComponent) {
        lists.add(universityComponent);
        log.info("学校新增子组织:" + JSON.toJSONString(universityComponent));
    }

    @Override
    protected void remove(UniversityComponent universityComponent) {
        lists.remove(universityComponent);
        log.info("学校裁剪组织:" + JSON.toJSONString(universityComponent));
    }

    @Override
    protected List<UniversityComponent> getChildern() {
        log.info("返回学校组织:" + JSON.toJSONString(lists));
        return lists;
    }

    @Override
    protected void operation() {
        System.out.println("----------------------" + name + "学校组织----------------------");
        lists.forEach(list -> {
            System.out.println("名称:" + list.getName() + ",备注:" + list.getDescription());
        });
    }
}

//学院树枝构件
@Slf4j
public class College extends UniversityComponent {

    private List<UniversityComponent> lists = new ArrayList<>();

    public College(String name, String university) {
        super(name, university);
    }

    @Override
    protected void add(UniversityComponent universityComponent) {
        lists.add(universityComponent);
        System.out.println("学院添加组织:" + JSON.toJSONString(universityComponent) + ",成功");
    }

    @Override
    protected void remove(UniversityComponent universityComponent) {
        lists.remove(universityComponent);
        System.out.println("学院删除组织:" + JSON.toJSONString(universityComponent) + ",成功");
    }

    @Override
    protected List<UniversityComponent> getChildern() {
        log.info("学院包含组织:" + JSON.toJSONString(lists));
        return lists;
    }

    @Override
    protected void operation() {
        System.out.println("-----------------" + name + "学院组织----------------");
        lists.forEach(list -> {
            System.out.println("名称:" + list.getName() + ",备注:" + list.getDescription());
        });
    }
}

//树枝节点(专业)
public class Profession extends UniversityComponent {

    public Profession(String name, String description) {
        super(name, description);
    }

    @Override
    protected void operation() {
        System.out.println("名称:" + name + ",备注:" + description);
    }
}

//测试类
public class Test {
    public static void main(String[] args) {

        University university = new University("清华大学", "中国数一数二的大学");

        College college1 = new College("艺术学院", "女生比较多的学院");
        College college2 = new College("经济管理学院", "五道口");

        Profession profession1 = new Profession("舞蹈专业", "专注于舞蹈");
        Profession profession2 = new Profession("播音专业", "专注于播音");
        Profession profession3 = new Profession("表演专业", "专注于表演");
        Profession profession4 = new Profession("金融投资", "专注于金融投资");

        college1.add(profession1);
        college1.add(profession2);
        college1.add(profession3);

        college2.add(profession4);

        university.add(college1);
        university.add(college2);

        university.operation();

        college1.operation();
        college2.operation();

    }
}

运行结果如下:
在这里插入图片描述

3.小结

1.组合模式具有较强扩展性,当需要更改组织关系时,只需调整内部关系,由于是通过接口进行关联,因此只需更改传入组织即可,不需要大规模修改代码;
2.简化了客户端的操作,客户端所给的对象一致,不需要考虑整体部分或者叶子节点的问题;
3.方便创建出复杂的层次结构。客户端不用理会组合里面的组成细节,容易添加节点或者叶子从而创建出复杂的树形结构;
4.需要遍历组织机构,或者处理的对象具有树形结构时,非常适合使用组合模式;
5.要求较高的抽象性,如果节点和叶子有很多差异性的话,比如很多方法和属性都不一样,不适合使用组合模式。

4.参考文献

1.《设计模式-可复用面向对象软件的基础》-Erich Gamma、Richard Helm、Ralph Johnson、John Vlissides
2.《可复用物联网Web3D框架的设计与实现》-程亮(知网)
3.https://www.bilibili.com/video/BV1G4411c7N4-尚硅谷设计模式
4.https://zhuanlan.zhihu.com/p/444784138

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

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

相关文章

Windows下一键搭建MBP系统,支持多种版本任意选择,免费永久使用,多系统使用新方案

Windows下一键搭建MBP系统,支持多种版本任意选择,免费永久使用,多系统使用新方案。 安装起来相当的简单,简单到只需要执行一行命令即可完成。使得游戏和开发可以兼顾,并且不用花费数万米的可以使用MBP。不仅如此,经过各项专业的测试,还有接近于原生的MBP系统性能。 效…

WinHex(二)

目录 1.我们打开WinHex&#xff0c;点击打开磁盘按钮 2.不同的文件在WinHex中有不同的文件显示 3.WinHex简单使用 4.删除之前所创建的虚拟磁盘 1.我们打开WinHex&#xff0c;点击打开磁盘按钮 2.不同的文件在WinHex中有不同的文件显示 3.WinHex简单使用 4.删除之前所创建的虚拟…

Java—Double类型进行加减乘除出错(精度)问题

前言&#xff1a; 我们知道&#xff0c;计算机在计算数据过程中都要先把源代码翻译成二进制的机器码&#xff0c;然后再进行相关的运算。然而在转换的过程中&#xff0c;有些十进制数无法用一个有限的二进制数来表示&#xff0c;就是说转换的时候出现了精度的丢失问题&#xff…

模型部署遇到的问题

1.不是有效的Win32应用程序 更改项目中的配置类型&#xff1a; 从网上下载的工程&#xff0c;之前人家是用来封装成库&#xff08;dll&#xff09;的&#xff0c;改成exe就好了。 vs学习问题 关于打开程序时不是有效的Win32应用程序_Lay_Nobody的博客-CSDN博客_vs不是有效的wi…

Spring Boot开发之SpringSercurity(续)

Spring Boot开发之SpringSercurity 一、授权1、打开上次项目以及数据库2、有的页面不登录也能访问&#xff0c;比如首页、登录以及注册等&#xff0c;因此对于某些请求不需要登录则放行这些接口(1)修改MySercurityConfig(2)修改TestController类(3)点击运行&#xff0c;在没登录…

数据抓取工具有哪些-数据抓取工具免费推荐的有哪些

随着社会的进步&#xff0c;科技的发展。不管是企业还是个人都清楚地明白了数据的重要性。不仅可以让我们掌握一手资源&#xff0c;同时还能通过数据更清楚竞争对手。同时也告别了手动复制粘贴的痛苦。 企业人员 通过爬取动态网页数据分析客户行为拓展新业务&#xff0c;分析…

java毕业设计健民中医药方网设计(附源码、数据库)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; Springboot mybatis Maven Vue 等等组成&#xff0c;B/…

NC5 二叉树根节点到叶子节点的所有路径和

描述 给定一个二叉树的根节点root&#xff0c;该树的节点值都在数字0−9 之间&#xff0c;每一条从根节点到叶子节点的路径都可以用一个数字表示。 1.该题路径定义为从树的根结点开始往下一直到叶子结点所经过的结点 2.叶子节点是指没有子节点的节点 3.路径只能从父节点到子节点…

java命令中的options

1. Java命令概述 安装JDK时&#xff0c;会使用java -version查看JDK版本&#xff0c;并验证安装是否成功直接输入java&#xff0c;会给出java命令的使用说明 -options&#xff1a;可选&#xff0c;java命令的命令行选项&#xff0c;多个选项使用空格分隔class&#xff1a;要启…

新人一看就懂:Dubbo3 + Nacos的RPC远程调用框架demo

文章目录一、前言Feign和Dubbo到底有啥区别&#xff0c;为啥大厂都爱用RPC框架&#xff1f;二、简介三、dubbo-api&#xff08;对外暴漏的接口&#xff09;1、pom依赖2、TestService接口四、dubbo-provider&#xff08;服务提供者&#xff09;1、pom依赖2、TestServiceImpl实现…

HCIP-Datacom OSPF进阶(一) 最常用的动态路由协议

目录 OSPF&#xff1a;开放式最短路径优先 OSPF配置方法&#xff1a; OSPF报文头部&#xff1a; OSPF报文类型&#xff1a; OSPF状态机&#xff1a; DR与BDR的作用&#xff1a; 设置选举DR时的优先级&#xff1a; OSPF的网络类型&#xff1a; 修改OSPF接口网络类型命令…

java毕业设计教学平台(附源码、数据库)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; Springboot mybatis Maven Vue 等等组成&#xff0c;B/…

Java实现五子棋小游戏(附源码)

Java进阶学习专栏&#xff1a;【Java】进阶篇 Java基础学习专栏&#xff1a;【Java】基础篇 文章目录一、游戏介绍二、效果展示三、代码展示1、登录页面2、算法程序3、棋盘实现四、资源下载五、文末总结一、游戏介绍 今天给大家分享一个用java写的小游戏——《五子棋》 &#…

计算机毕业设计SSM电影网站系统【附源码数据库】

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【编程题】【Scratch三级】2021.12 数星星

数星星 Goblin有个很厉害的魔法:他一挥手就可以点亮夜空中五彩斑斓的星星灯。 1. 准备工作 (1)删除小猫角色,添加"Goblin"角色,并删除Goblin角色的造型"golblin-a"、“goblin-c"和"goblin-d”,添加角色"Star"; (2)添加“Sta…

Matlab之自适应位移相位中心天线脉冲消除器(附源码)

目录 一、何时使用自适应DPCA脉冲消除器 二、自适应DPCA脉冲消除器可抑制杂波和干扰 三、程序 一、何时使用自适应DPCA脉冲消除器 考虑需要抑制杂波的机载雷达系统 返回并可能干扰干扰。根据以下任何一项 条件下&#xff0c;可以选择自适应 DPCA &#xff08;ADPCA&#xf…

数据挖掘与分析应用:tableau可视化数据分析,仪表盘,折线图,饼图,条形图,地图,散点图,区域图,表格,数据分析引用

数据挖掘与分析应用&#xff1a;tableau可视化数据分析&#xff0c;仪表盘&#xff0c;折线图&#xff0c;饼图&#xff0c;条形图&#xff0c;地图&#xff0c;散点图&#xff0c;区域图&#xff0c;表格&#xff0c;数据分析引用 2022找工作是学历、能力和运气的超强结合体&…

Java集合

一、集合概述 1、数组的特点 数组的大小是固定的&#xff0c;一旦创建后&#xff0c;数组的大小是无法改变的。数组只能存储相同类型的数据。数组查询效率高(有索引&#xff0c;元素内存连续分配)&#xff0c;增删效率低(不断的扩容)。 2、数组和集合的区别 相同点&#xff1…

【Designing ML Systems】第 6 章 :模型开发和离线评估

&#x1f50e;大家好&#xff0c;我是Sonhhxg_柒&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f4dd;个人主页&#xff0d;Sonhhxg_柒的博客_CSDN博客 &#x1f4c3; &#x1f381;欢迎各位→点赞…

目标检测论文解读复现之三:基于改进YOLOv7的X光图像旋转目标检测

目标检测论文解读复现 文章目录目标检测论文解读复现前言一、摘要二、网络模型及核心创新点三、应用数据集四、实验效果五、实验结论六、投稿期刊介绍前言 此前出了目标改进算法专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果…