组合模式(结构型)
目录
一、前言
二、透明组合模式
三、安全组合模式
四、总结
一、前言
组合模式(Composite Pattern)是一种结构型设计模式,将对象组合成树形结构以表示“部分-整体”得层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
组合模式由以下角色组成:
Component(抽象组件):
一般是接口或者抽象类,是叶子构件和容器构件对象声明接口,抽象出访问以及管理子构件的方法,可以看做是根节点
Leaf(叶子结点):
在组合中表示叶子节点对象,叶子节点没有子节点,也就没有子构件
Composite(复合节点):
复合节点可以包含子节点,子节点可以是叶子节点,也可以是其他复合节点。可以看做是树枝节点
整个组合模式的结构图:
二、透明组合模式
组合模式分为透明和安全两种方式,在透明方式中,抽象组件中会声明所有类中的方法,客户端无法区别树叶对象和树枝对象,对客户端是透明的。但在树叶节点中,本来没有添加、删除放大,但却要实现它,是没有意义的。
比如公司组织建构,公司有总公司,总公司下有财务部门、技术部门等,还有分公司,分公司也有财务部门,技术部门等。如果按照传统方式,总公司的财务部门、技术部门等需要代码实现,分公司的财务部门、技术部门也需要代码实现,但现实中这些部门的职责差不多,分公司其实可以复用总公司的财务部门、技术部门类。
根据组合模式,我们便有以下代码实现:
抽象组件Component类,即根节点:
public abstract class Component {abstract void add(Component component);abstract void remove(Component component);abstract void display(int depth);abstract void operation();
}
复合节点Composite类,即树枝节点:
public class Composite extends Component{private List<Component> children = new ArrayList<>();private String name;public Composite(String name) {this.name = name;}@Overridevoid add(Component component) {children.add(component);}@Overridevoid remove(Component component) {children.remove(component);}@Overridevoid display(int depth) {System.out.println("深度:" + depth + " 名称:" + name);for (Component component : children) {component.display(depth + 1);}}@Overridevoid operation() {for (Component component : children){component.operation();}}
}
叶子节点财务部门LeafOne类:
public class LeafOne extends Component{private String name;public LeafOne(String name) {this.name = name;}@Overridevoid add(Component component) {}@Overridevoid remove(Component component) {}@Overridevoid display(int depth) {System.out.println("深度:" + depth + " 名称:" + name);}@Overridevoid operation() {System.out.println(name + "财务操作");}
}
叶子节点财务部门LeafTwo类:
public class LeafTwo extends Component{private String name;public LeafTwo(String name) {this.name = name;}@Overridevoid add(Component component) {}@Overridevoid remove(Component component) {}@Overridevoid display(int depth) {System.out.println("深度:" + depth + " 名称:" + name);}@Overridevoid operation() {System.out.println(name + "技术操作");}
}
客户端调用类:
public class Client {public static void main(String[] args) {Component component = new Composite("北京总公司");component.add(new LeafOne("北京总公司财务部门"));component.add(new LeafTwo("北京总公司技术部门"));Component component1 = new Composite("上海分公司");component1.add(new LeafOne("上海分公司财务部门"));component1.add(new LeafTwo("上海分公司技术部门"));component.add(component1);Component component2 = new Composite("深圳分公司");component2.add(new LeafOne("深圳分公司财务部门"));component2.add(new LeafTwo("深圳分公司技术部门"));component.add(component2);System.out.println("公司架构:");component.display(1);System.out.println("职能:");component.operation();}
}
运行结果:
三、安全组合模式
相较于透明方式的组合模式,安全方式主要在抽象组件中不包含添加、删除操作,客户端调用中区分复合节点和叶子节点。
抽象组件Component类:
public abstract class Component {abstract void display(int depth);abstract void operation();
}
复合节点Composite类:
public class Composite extends Component{private List<Component> children = new ArrayList<>();private String name;public Composite(String name) {this.name = name;}public void add(Component component) {children.add(component);}public void remove(Component component) {children.remove(component);}@Overridevoid display(int depth) {System.out.println("深度:" + depth + " 名称:" + name);for (Component component : children) {component.display(depth + 1);}}@Overridevoid operation() {for (Component component : children){component.operation();}}
}
叶子节点财务部门LeafOne类:
public class LeafOne extends Component {private String name;public LeafOne(String name) {this.name = name;}@Overridevoid display(int depth) {System.out.println("深度:" + depth + " 名称:" + name);}@Overridevoid operation() {System.out.println(name + "财务操作");}
}
叶子节点财务部门LeafTwo类:
public class LeafTwo extends Component{private String name;public LeafTwo(String name) {this.name = name;}@Overridevoid display(int depth) {System.out.println("深度:" + depth + " 名称:" + name);}@Overridevoid operation() {System.out.println(name + "技术操作");}
}
客户端调用:
public class Client {public static void main(String[] args) {Composite composite = new Composite("北京总公司");composite.add(new LeafOne("北京总公司财务部门"));composite.add(new LeafTwo("北京总公司技术部门"));Composite composite1 = new Composite("上海分公司");composite1.add(new LeafOne("上海分公司财务部门"));composite1.add(new LeafTwo("上海分公司技术部门"));composite.add(composite1);Composite composite2 = new Composite("深圳分公司");composite2.add(new LeafOne("深圳分公司财务部门"));composite2.add(new LeafTwo("深圳分公司技术部门"));composite.add(composite2);System.out.println("公司架构:");composite.display(1);System.out.println("职能:");composite.operation();}
}
运行结果:
四、总结
优点与缺点
优点:
1、高层模块(客户端)调用简单。组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码
2、节点自由增加,更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”
缺点:
1、在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则
2、设计较复杂,客户端需要花更多时间理清类之间的层次关系
3、不容易限制容器中的构件
4、不容易用继承的方法来增加构件的新功能
使用场景:
当需求中是体现部分与整体层次的结构时,以及希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑组合模式。
Spring中IOC就使用到组合模式,通过将组件组合成树形结构,实现了对象的依赖关系管理和生命周期控制。比如Spring中的CompositeCacheManager,Spring用来管理多个CacheManager的复合类。
文件系统:
组合模式可以用来表示文件系统的层次结构,使得客户端可以以统一的方式操作文件和文件夹,例如创建、删除、移动等。
组织机构:
组合模式可以用于表示组织机构的层次结构,例如公司的组织结构可以以树形结构来表示,根节点表示公司,子节点表示部门,叶子节点表示员工。使用组合模式可以统一地管理公司的组织结构,例如添加、删除部门或员工,查找某个部门的员工等。
图形界面控件:
图形界面中的控件可以被看作是一个层次结构,例如窗口控件可以包含按钮控件和文本框控件,按钮控件又可以包含图片控件等。组合模式可以用来表示控件的层次结构,使得客户端可以以统一的方式操作控件,例如添加、删除、遍历等。
菜单和菜单项:
在图形界面中,菜单可以包含菜单项,菜单项可以是子菜单或者普通的操作项。组合模式可以用来表示菜单和菜单项的层次结构,使得客户端可以以统一的方式操作菜单和菜单项,例如添加、删除、遍历等。
相关文章:

组合模式(结构型)
目录 一、前言 二、透明组合模式 三、安全组合模式 四、总结 一、前言 组合模式(Composite Pattern)是一种结构型设计模式,将对象组合成树形结构以表示“部分-整体”得层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。 组合模式由以下角色组成…...

Pspice for TI学习
Pspice for TI中PSpice Part Search空白解决方法 配置环境变量 Cad_PSpice_TI_Regr_Srvr https://software-dl.ti.com/pspice/S009 重新安装2023版的Pspice Pspice安装链接 打开新安装的软件即可发现PSpice Part Search可以正常使用了 VSIN各参赛的含义 VOFF直流偏置VAMPL…...

LoRA的原理简介
在文章开始前先澄清一个概念,需要区分形近的单词"LoRa"(long range),这是一项通信技术。熟悉物联网行业的朋友相对会比较熟悉LoRa这项技术,因为有些设备比如电梯的控制就使用了这个技术进行本地数据和命令的…...

安卓使用Fiddler抓包 2024
简介 最近试了一下安卓使用fiddler 抓包,发现https包基本都会丢失。原因是Anandroid 7版本针对ssl安全性做了加强,不认可用户的证书。我们要做的就是把fiddler导出的证书进过处理后放置到系统证书目录下面,这样才能抓包https请求。 这里使用…...
【前端每日基础】day2 const var const的区别
var: 在早期的 JavaScript 中,var 是声明变量的唯一方式。它有以下特点: var 声明的变量是函数作用域(function-scoped),而不是块作用域(block-scoped),这意味着它们在整个函数内部都…...

乡村振兴的文化旅游融合:整合乡村文化资源与旅游资源,发展文化旅游产业,提升美丽乡村的文化内涵和旅游吸引力
一、引言 随着城市化进程的加速和人们精神文化需求的日益增长,乡村旅游逐渐成为旅游市场的新热点。乡村振兴战略的提出,为乡村旅游的发展提供了新的契机。在这一背景下,如何整合乡村文化资源与旅游资源,发展文化旅游产业…...
力扣题目101:对称二叉树
作者介绍:10年大厂数据\经营分析经验,现任大厂数据部门负责人。 会一些的技术:数据分析、算法、SQL、大数据相关、python 欢迎加入社区:码上找工作 作者专栏每日更新: LeetCode解锁1000题: 打怪升级之旅 python数据分析…...

struct和union大小计算规则
Union 一:联合类型的定义 联合也是一种特殊的自定义类型,这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以联合也叫共用体) 比如:共用了 i 这个较大的空间 二: 联合的…...
数据库课程设计《基于Spring Boot + MyBatis + MySQL 实现Java医院药品管理系统》+源代码
文章目录 源代码下载地址项目介绍项目功能 项目备注源代码下载地址 源代码下载地址 点击这里下载源码 项目介绍 项目功能 库存管理 登记入库的药品。 登记出库的药品。 每日检查库存下限,报警。 每日检查过期的药品,报警并做退回销毁处理。 对有问题…...

【每日力扣】98. 验证二叉搜索树 与 108. 将有序数组转换为二叉搜索树
🔥 个人主页: 黑洞晓威 😀你不必等到非常厉害,才敢开始,你需要开始,才会变的非常厉害 98. 验证二叉搜索树 给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&a…...
Django3 个人开发笔记
查询函数 select_related 在 Django ORM 中,select_related 是一个查询性能优化工具,用于解决关联对象的查询效率问题。当你有两个通过外键(ForeignKey)或一对一字段(OneToOneField)连接的模型时…...

【全开源】Java U U跑腿同城跑腿小程序源码快递代取帮买帮送源码小程序+H 5+公众号跑腿系统
特色功能: 智能定位与路线规划:UU跑腿小程序能够利用定位技术,为用户提供附近的跑腿服务,并自动规划最佳路线,提高配送效率。订单管理:包括订单查询、订单状态更新、订单评价等功能,全行业覆盖…...

物联网实战--平台篇之(五)账户界面
目录 一、界面框架 二、首页(未登录) 三、验证码登录 四、密码登录 五、帐号注册 六、忘记密码 本项目的交流QQ群:701889554 物联网实战--入门篇https://blog.csdn.net/ypp240124016/category_12609773.html 物联网实战--驱动篇https://blog.csdn.net/ypp240124016/cat…...

9. Django Admin后台系统
9. Admin后台系统 Admin后台系统也称为网站后台管理系统, 主要对网站的信息进行管理, 如文字, 图片, 影音和其他日常使用的文件的发布, 更新, 删除等操作, 也包括功能信息的统计和管理, 如用户信息, 订单信息和访客信息等. 简单来说, 它是对网站数据库和文件进行快速操作和管…...
ELK+kafka日志采集
ElasticSeach(存储日志信息) Logstash(搬运工) Kibana 连接ElasticSeach图形化界面查询日志 ELK采集日志的原理: 在每个服务器上安装LogstashLogstash需要配置固定读取某个日志文件Logstash将日志文件格式化为json的…...
【C++ list所有函数举例如何使用】
C 中的 std::list 是一个双向链表,提供了在列表中添加、删除、访问元素等操作的方法。以下是一些常用的 std::list 函数以及如何使用它们的示例: push_back(const T& value): 在列表的末尾添加一个值为 value 的元素。 std::list<int> mylis…...

HTML5(1)
目录 一.HTML5(超文本(链接)标记(标签<>)语言) 1.开发环境(写代码,看效果) 2.vscode 使用 3.谷歌浏览器使用 4.标签语法 5.HTML基本骨架(网页模板) 6.标签的…...

【LAMMPS学习】八、基础知识(6.2)LAMMPS GitHub 教程
8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语,以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…...
专业习惯:避开本地语言,使用通用语言
如果你的目标是走一步看一步,那躺平就得了,学习什么的都没有必要。如果你的目标是远方,那么就需要未雨绸缪。 在工作之中,本地语言及习惯固然可用,但非常局限,随便换一个地方和场景,别人就难以理…...

【Leetcode每日一题】 综合练习 - 逆波兰表达式求值(难度⭐⭐)(73)
1. 题目解析 题目链接:150. 逆波兰表达式求值 这个问题的理解其实相当简单,只需看一下示例,基本就能明白其含义了。 2.算法原理 数据结构选择: 使用栈(stack<int>)来存储操作数,以便进…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...

PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...