Java组合模式:构建多层次公司组织架构
在现实生活中,常常会遇到用树形结构组织的一些场景,比如国家省市,学校班级,文件目录,分级导航菜单,以及典型的公司组织架构,整个层次结构自顶向下呈现一颗倒置的树。这种树形结构在面向对象的世界中非常适合用组合模式来处理。
一,概述
组合模式(Composite Pattern),又叫做“部分-整体”模式,是一种结构型设计模式,它允许将对象组织成树状结构,以表示“部分-整体”的层次结构。在这种结构中,可以将相同操作应用于部分和整体,从而实现对单个对象和组合对象的一致性处理。怎么理解单个对象和组合对象,比如一颗倒置的节点树,其中的叶子节点就是单个对象,每个分支节点和其下的所有子节点共同构成组合对象。
组合模式一般包含以下角色:
- 抽象构件(Component):为单个对象和组合对象声明公共接口,定义共有的行为或属性,如添加、删除、获取子节点等方法。
- 叶子构件(Leaf):即单个的对象,表示树形结构中没有子节点的对象,实现了抽象构件中的方法。
- 组合构件(Composite):即组合对象,包含一组子对象,同时实现了抽象构件中添加、删除、获取子节点等方法。

优点
- 提供统一的操作接口,简化客户端代码:客户端代码可以一致地处理单个对象和组合对象,无需区分它们的类型,使客户端代码更加简洁和统一。
- 提升系统灵活性和可扩展性:可以很方便地通过添加新的组合对象或叶子对象来扩展树形结构,并且可以动态地添加、删除和修改对象。
缺点
- 限制了组合对象的类型:组合模式中的组合对象必须实现相同的接口或继承相同的父类。这可能会限制组合对象的类型,使其无法满足特定的需求。
- 可能导致系统过于一般化:组合模式的使用可能导致系统过于一般化,将特定的操作和行为放在组合模式中可能不太合适。
- 增加了系统的复杂性:引入组合模式会增加系统的复杂性,需要更多的类和接口来表示组合结构,增加了代码的数量和理解难度。
适用场景
- 需要表示“部分-整体”层次结构的情况,如树状结构、目录结构等。
- 希望能够以统一的方式处理单个对象和组合对象时。
- 需要动态地添加、删除和修改对象,希望系统具有良好的扩展性时。
二,模拟公司组织架构
案例分析
接下来我们用组合模式来模拟实现下公司组织架构,使得我们可以动态管理公司人员。如上图所示,所有的叶子节点表示普通员工,是单个的对象。所有的分支节点包括根节点表示领导,每个领导都含有下属员工,总裁的下属就是主管,每个领导及其直接下属就构成组合对象。不管是总裁、主管还是普通员工,他们都是公司的雇员,这就是员工和领导的共性。
代码实现
步骤1:创建抽象构件—Employee接口,表示雇员。
public interface Employee {//添加下属员工void add(Employee e);//移除下属员工void remove(Employee e);//获取所有下属员工List<Employee> getSubordinates();//打印员工信息void info();
}
步骤2:创建叶子构件—Worker类,实现Employee接口,表示最底层的员工。对于的员工的管理操作,提供空实现即可。
public class Worker implements Employee{//员工姓名private String name;public Worker(String name) {this.name = name;}@Overridepublic void add(Employee e) {}@Overridepublic void remove(Employee e) {}@Overridepublic List<Employee> getSubordinates() {return null;}@Overridepublic void info() {System.out.println("员工-"+name);}
}
步骤3:创建组合构件—Leader类,实现Employee接口,表示含有下属的领导。代码中用一个集合表示该领导的下属。
public class Leader implements Employee{//领导姓名private String name;//下属集合private List<Employee> subordinates;public Leader(String name) {this.name = name;this.subordinates= new ArrayList<>();}@Overridepublic void add(Employee e) {subordinates.add(e);}@Overridepublic void remove(Employee e) {subordinates.remove(e);}@Overridepublic List<Employee> getSubordinates() {return subordinates;}@Overridepublic void info() {System.out.println("领导-"+name);for(Employee e:subordinates){e.info();}}
}
步骤4:客户端测试。
public class Client {public static void main(String[] args) {Employee ceo=new Leader("ceo");Employee devLeader=new Leader("devLeader");Employee fatLeader=new Leader("fatLeader");ceo.add(devLeader);ceo.add(fatLeader);Employee devWorker01=new Worker("devWorker01");Employee devWorker02=new Worker("devWorder02");devLeader.add(devWorker01);devLeader.add(devWorker02);Employee fatWorker01=new Worker("fatWorker01");Employee fatWorker02=new Worker("fatWorder02");fatLeader.add(fatWorker01);fatLeader.add(fatWorker02);//打印整个公司架构ceo.info();System.out.println();//打印开发部门架构devLeader.info();System.out.println();//测试部门开除员工fatWorker01后的人员结构fatLeader.remove(fatWorker01);fatLeader.info();}
}
测试结果

三,总结
通过本篇文章的案例学习,可以看出组合模式在处理树状结构场景时,非常有用。在实际项目中,如果遇到需要表示对象的“部分-整体”关系,并希望用户能够忽略组合对象和单个对象之间的差异,可以考虑使用组合模式。它可以简化客户端操作,并提升系统灵活性和扩展性。不过,它也可能增加系统的复杂度和理解难度,我们应该根据实际需求进行权衡。
好了,希望这篇文章对你的学习有所帮助,在此感谢你的阅读,我们下次再见!

相关文章:
Java组合模式:构建多层次公司组织架构
在现实生活中,常常会遇到用树形结构组织的一些场景,比如国家省市,学校班级,文件目录,分级导航菜单,以及典型的公司组织架构,整个层次结构自顶向下呈现一颗倒置的树。这种树形结构在面向对象的世…...
Langchain-ChatGLM:基于本地知识库问答
文章目录 ChatGLM与Langchain简介ChatGLM-6B简介ChatGLM-6B是什么ChatGLM-6B具备的能力ChatGLM-6B具备的应用 Langchain简介Langchain是什么Langchain的核心模块Langchain的应用场景 ChatGLM与Langchain项目介绍知识库问答实现步骤ChatGLM与Langchain项目特点 项目主体结构项目…...
设计模式十 适配器模式
适配器模式 适配器模式是一种结构型设计模式。作用:当接口无法和类匹配到一起工作时,通过适配器将接口变换成可以和类匹配到一起的接口。(注:适配器模式主要解决接口兼容性问题) 适配器的优点与缺点: 优…...
1.6 初探JdbcTemplate操作
一、JdbcTemplate案例演示 1、创建数据库与表 (1)创建数据库 执行命令:CREATE DATABASE simonshop DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; 或者利用菜单方式创建数据库 - simonshop 打开数据库simonshop &#x…...
为什么要用线程池?
线程池是一种管理和复用线程资源的机制,它由一个线程池管理器和一组工作线程组成。线程池管理器负责创建和销毁线程池,以及管理线程池中的工作线程。工作线程则负责执行具体的任务。 线程池的主要作用是管理和复用线程资源,避免了线程的频繁…...
c语言的预处理和编译
预处理 文件包含 当预处理器发现#include指令时,会查看后面的文件名并把文件的内容包含到当前文件中 两种写法 尖括号:引用的是编译器的库路径里面的头文件。 双引号:引用的是程序目录中相对路径中的头文件,如果找不到再去上面…...
网络安全必学 SQL 注入
1.1 .Sql 注入攻击原理 SQL 注入漏洞可以说是在企业运营中会遇到的最具破坏性的漏洞之一,它也是目前被利用得最多的漏洞。要学会如何防御 SQL 注入,首先我们要学习它的原理。 针对 SQL 注入的攻击行为可描述为通过在用户可控参数中注入 SQL 语法&#x…...
Docker基础知识详解
✅作者简介:热爱Java后端开发的一名学习者,大家可以跟我一起讨论各种问题喔。 🍎个人主页:Hhzzy99 🍊个人信条:坚持就是胜利! 💞当前专栏:文章 🥭本文内容&am…...
腾讯、阿里入选首批“双柜台证券”,港股市场迎盛夏升温?
6月5日,香港交易所发布公告,将于6月19日在香港证券市场推出“港币-人民币双柜台模式”,当日确定有21只证券指定为双柜台证券。同时,港交所还表示,在双柜台模式推出前,更多证券或会被接纳并加入双…...
CentOS7 使用Docker 安装MySQL
CentOS7 使用Docker 安装MySQL Docker的相关知识本篇不会再概述,有疑惑的同学请自行查找相关知识。本篇只是介绍如何在CentOS7下使用Docker安装相应的镜像。 可登陆Docker官网 https://docs.docker.com 之后可以跟着官方的步骤进行安装。 clipboard.png 具体安装过…...
注解和反射复习
注解 注解:给程序和人看的,被程序读取,jdk5.0引用 内置注解 override:修饰方法,方法声明和重写父类方法, Deprecated:修饰,不推荐使用 suppressWarnings用来抑制编译时的警告,必须添加一个或多个参数s…...
RocketMQ的demo代码
下面是一个使用Java实现的RocketMQ示例代码,用于发送和消费消息: 首先,您需要下载并安装RocketMQ,并启动NameServer和Broker。 接下来,您可以使用以下示例代码来发送和消费消息: Producer.java文件&…...
C++ 连接、操作postgreSQL(基于libpq库)
C++ 连接postgreSQL(基于libpq库) 1.环境2.数据库操作2.1. c++ 连接数据库2.2. c++ 删除数据库属性表内容2.3. c++ 插入数据库属性表内容2.4 c++ 关闭数据库1.环境 使用libpq库来链接postgresql数据库,主要用到的头文件是这个: #include "libpq-fe.h"2.数据库操…...
Node.js技术简介及其在Web开发中的应用
Node.js是一个基于Chrome V8引擎的JavaScript运行时环境,使得JavaScript能够在服务器端运行。Node.js采用事件驱动、非阻塞I/O模型,能够处理大量并发请求,非常适合处理I/O密集型的应用程序。本文将介绍Node.js的特点、优势以及在Web开发中的应…...
时间序列分析:原理与MATLAB实现
2023年9月数学建模国赛期间提供ABCDE题思路加Matlab代码,专栏链接(赛前一个月恢复源码199,欢迎大家订阅):http://t.csdn.cn/Um9Zd 目录 1. 时间序列分析简介 2. 自回归模型(AR) 2.1. 参数估计 2.2. MATLAB实现...
mysql排序之if(isnull(字段名),0,1),字段名 或者 if(isnull(字段名),1,0),字段名
mysql排序之if(isnull(字段名),0,1),字段名 或者 if(isnull(字段名),1,0),字段名 默认情况下,MySQL将null算作最小值。如果想要手动指定null的顺序,可以这样处理: 将null强制放在最前 //null, null, 1,2,3,4(默认就是这样&#…...
华为OD机试真题 Java 实现【递增字符串】【2023Q1 200分】,附详细解题思路
一、题目描述 定义字符串完全由“A’和B"组成,当然也可以全是"A"或全是"B。如果字符串从前往后都是以字典序排列的,那么我们称之为严格递增字符串。 给出一个字符串5,允许修改字符串中的任意字符,即可以将任何的"A"修改成"B,也可以将…...
合并文件解决HiveServer2内存溢出方案
一、文件过多导致HiveServer2内存溢出 1.1查看表文件个数 desc formatted yanyu.tmp• 表文件数量为6522102 1.2查看表文件信息 hadoop fs -ls warehouse/yanyu.db/tmp• 分区为string 类型的time字段,分了2001个区。 1.3.查看某个分区下的文件个数为10000个 …...
韧性数据安全体系缘起与三个目标 |CEO专栏
今年4月,美创科技在数据安全领域的新探索——“韧性”数据安全防护体系框架正式发布亮相。 为帮您更深入了解“韧性数据安全”,我们特别推出专栏“构建适应性进化的韧性数据安全体系”,CEO柳遵梁亲自执笔,进行系列解读分享。 首期…...
华为OD机试真题 Java 实现【火车进站】【牛客练习题】
一、题目描述 给定一个正整数N代表火车数量,0<N<10,接下来输入火车入站的序列,一共N辆火车,每辆火车以数字1-9编号,火车站只有一个方向进出,同时停靠在火车站的列车中,只有后进站的出站了,先进站的才能出站。 要求输出所有火车出站的方案,以字典序排序输出。 …...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...
pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...
零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程
STM32F1 本教程使用零知标准板(STM32F103RBT6)通过I2C驱动ICM20948九轴传感器,实现姿态解算,并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化,适合嵌入式及物联网开发者。在基础驱动上新增…...
es6+和css3新增的特性有哪些
一:ECMAScript 新特性(ES6) ES6 (2015) - 革命性更新 1,记住的方法,从一个方法里面用到了哪些技术 1,let /const块级作用域声明2,**默认参数**:函数参数可以设置默认值。3&#x…...
《Offer来了:Java面试核心知识点精讲》大纲
文章目录 一、《Offer来了:Java面试核心知识点精讲》的典型大纲框架Java基础并发编程JVM原理数据库与缓存分布式架构系统设计二、《Offer来了:Java面试核心知识点精讲(原理篇)》技术文章大纲核心主题:Java基础原理与面试高频考点Java虚拟机(JVM)原理Java并发编程原理Jav…...
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__ is not explicitly defined.
这个警告表明您在使用Vue的esm-bundler构建版本时,未明确定义编译时特性标志。以下是详细解释和解决方案: 问题原因: 该标志是Vue 3.4引入的编译时特性标志,用于控制生产环境下SSR水合不匹配错误的详细报告1使用esm-bundler…...
