Gof23设计模式之组合模式
1.定义
组合模式又名部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。

2.结构
组合模式主要包含三种角色:
- 抽象根节点(Component):定义系统各层次对象的共有方法和属性,可以预先定义一些默认行为和属性。
- 树枝节点(Composite):定义树枝节点的行为,存储子节点,组合树枝节点和叶子节点形成一个树形结构。
- 叶子节点(Leaf):叶子节点对象,其下再无分支,是系统层次遍历的最小单位。
3.实现
我们在访问别的一些管理系统时,经常可以看到类似的菜单。一个菜单可以包含菜单项(菜单项是指不再包含其他内容的菜单条目),也可以包含带有其他菜单项的菜单,因此使用组合模式描述菜单就很恰当,我们的需求是针对一个菜单,打印出其包含的所有菜单以及菜单项的名称。

/*** @author 晓风残月Lx* @date 2023/7/12 16:38* 菜单组件 (抽象根节点)*/
public abstract class MenuComponent {// 菜单组件的名称protected String name;// 菜单组件的层级protected int level;// 添加子菜单public void add(MenuComponent menuComponent) {throw new UnsupportedOperationException();}// 移除子菜单public void remove(MenuComponent menuComponent) {throw new UnsupportedOperationException();}// 获取指定的子菜单public MenuComponent getChild(int index) {throw new UnsupportedOperationException();}// 获取菜单或者菜单项的名称public String getName() {return name;}// 打印菜单名称的方法(包含子菜单和子菜单项)public abstract void print();}import java.util.ArrayList;
import java.util.List;/*** @author 晓风残月Lx* @date 2023/7/12 16:43* 菜单类(树枝节点)*/
public class Menu extends MenuComponent {// 菜单可以有多个子菜单或者子菜单项private List<MenuComponent> menuComponentList = new ArrayList<MenuComponent>();public Menu(String name, int level) {this.name = name;this.level = level;}@Overridepublic void add(MenuComponent menuComponent) {menuComponentList.add(menuComponent);}@Overridepublic void remove(MenuComponent menuComponent) {menuComponentList.remove(menuComponent);}@Overridepublic MenuComponent getChild(int index) {return menuComponentList.get(index);}@Overridepublic void print() {// 打印菜单名称for(int i = 0; i < level; i++) {System.out.print("--");}System.out.println(name);// 打印子菜单名称或者子菜单项名称for (MenuComponent menuComponent : menuComponentList) {menuComponent.print();}}
}/*** @author 晓风残月Lx* @date 2023/7/12 16:47* 菜单项类(叶子节点)*/
public class MenuItem extends MenuComponent {public MenuItem(String name, int level) {this.name = name;this.level = level;}@Overridepublic void print() {for(int i = 0; i < level; i++) {System.out.print("--");}// 打印菜单项的名称System.out.println(name);}
}/*** @author 晓风残月Lx* @date 2023/7/12 16:49*/
public class Client {public static void main(String[] args) {// 创建菜单树MenuComponent menu1 = new Menu("菜单管理", 2);menu1.add(new MenuItem("页面菜单", 3));menu1.add(new MenuItem("展开菜单", 3));menu1.add(new MenuItem("编辑菜单", 3));MenuComponent menu2 = new Menu("权限管理", 2);menu2.add(new MenuItem("页面访问", 3));menu2.add(new MenuItem("提交保存", 3));MenuComponent menu3 = new Menu("角色管理", 2);menu3.add(new MenuItem("新增角色", 3));// 创建一级菜单MenuComponent component = new Menu("系统管理", 1);component.add(menu1);component.add(menu2);component.add(menu3);component.print();}}

4.组合模式的分类
在使用组合模式时,根据抽象构件类的定义形式,我们可将组合模式分为透明组合模式和安全组合模式两种形式。
-
透明组合模式
透明组合模式中,抽象根节点角色中声明了所有用于管理成员对象的方法,比如在示例中
MenuComponent声明了add、remove、getChild方法,这样做的好处是确保所有的构件类都有相同的接口。透明组合模式也是组合模式的标准形式。透明组合模式的缺点是不够安全,因为叶子对象和容器对象在本质上是有区别的,叶子对象不可能有下一个层次的对象,即不可能包含成员对象,因此为其提供 add()、remove() 等方法是没有意义的,这在编译阶段不会出错,但在运行阶段如果调用这些方法可能会出错(如果没有提供相应的错误处理代码)
-
安全组合模式
在安全组合模式中,在抽象构件角色中没有声明任何用于管理成员对象的方法,而是在树枝节点
Menu类中声明并实现这些方法。安全组合模式的缺点是不够透明,因为叶子构件和容器构件具有不同的方法,且容器构件中那些用于管理成员对象的方法没有在抽象构件类中定义,因此客户端不能完全针对抽象编程,必须有区别地对待叶子构件和容器构件。
5.优点
- 组合模式可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,它让客户端忽略了层次的差异,方便对整个层次结构进行控制。
- 客户端可以一致地使用一个组合结构或其中单个对象,不必关心处理的是单个对象还是整个组合结构,简化了客户端代码。
- 在组合模式中增加新的树枝节点和叶子节点都很方便,无须对现有类库进行任何修改,符合“开闭原则”。
- 组合模式为树形结构的面向对象实现提供了一种灵活的解决方案,通过叶子节点和树枝节点的递归组合,可以形成复杂的树形结构,但对树形结构的控制却非常简单。
6.使用场景
组合模式正是应树形结构而生,所以组合模式的使用场景就是出现树形结构的地方。比如:文件目录显示,多级目录呈现等树形结构数据的操作。
相关文章:
Gof23设计模式之组合模式
1.定义 组合模式又名部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。 2.结构 组合模式主要包含三种…...
龙芯积极研发二进制翻译,提升软硬件兼容性,提高LoongArch架构
根据8月8日Phoronix报道,龙芯正在积极研发龙芯二进制翻译功能(Loongson Binary Translationm,LBT)以提高LoongArch架构与其他处理器(如MIPS/x86/Arm)的二进制翻译能力,这重要举措将显著提升龙芯…...
3天爆肝整理,自动化测试-YAML文件读写实战(超细总结)
目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 YAML 简介 YAML&…...
算法通关村——透彻理解二分查找
1. 循环法 public static int binarySearch(int[] arr, int low, int high, int target) {while (low < high) {// 这样写主要是避免溢出的情况,以及>>优先级小于,避免出现死循环int mid low ((high - low) >> 1);if (arr[mid] target…...
PAT(Advanced Level)刷题指南 —— 第六弹(⭐有点难度⭐)
一、1010 Radix 1. 问题重述 2. Sample Input1 6 110 1 103. Sample Output1 24. Sample Input 2 1 ab 1 25. Sample Output 2...
个人对智能家居平台选择的思考
本人之前开发过不少MicroPython程序,其中涉及到自动化以及局域网控制思路,也可以作为智能家居的实现方式。而NodeMCUESPHome的方案具有方便添加硬件、容易更新程序和容量占用小的优势,本人也查看过相关教程后感觉部署ESPHome和编译固件的步骤…...
无涯教程-Lua - while语句函数
只要给定条件为真,Lua编程语言中的 while 循环语句就会重复执行目标语句。 while loop - 语法 Lua编程语言中 while 循环的语法如下- while(condition) dostatement(s) end while loop - 流程图 在这里,需要注意的关键是 while 循环可能根本不执行。…...
MySql学习3:常用函数
常用字符串函数 CHAR_LENGTH(s):返回字符串的长度 select *, char_length(name) as nameLength from emp;CONCAT(s1,s2…sn):字符串拼接 select name,concat(name,入职时间:,entrydata) as 入职时间 from emp;CONCAT_WS(x, s1,s2…sn)&a…...
24届近5年江南大学自动化考研院校分析
今天给大家带来的是江南大学控制考研分析 满满干货~还不快快点赞收藏 一、江南大学 学校简介 江南大学(Jiangnan University)是国家“双一流”建设高校,“211工程”、“985工程优势学科创新平台”重点建设高校,入选…...
C++ 数组
数组是具有一定顺序关系的若干对象的集合体,组成数组的对象称为该数组的元素。 数组元素用数组名与带方括号的下标表示,同一数组的各个元素具有相同的类型。数组可以由除void型以外的任何一种类型构成,构成数组的类型和数组之间的关系&#x…...
Android LinearLayout dynamic add child ImageView,Glide load,kotlin
Android LinearLayout dynamic add child ImageView,Glide load,kotlin images.xml <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"andro…...
HTML 是什么?它的全称是什么?
聚沙成塔每天进步一点点 专栏简介HTML是什么?HTML的全称是什么?写在最后 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅!这个专栏是为那些对We…...
ATF(TF-A)安全通告
目录计划如下,相关内容补充中,待完成后进行超链接,敬请期待,欢迎关注 1、Advisory TFV-1 (CVE-2016-10319) 2、Advisory TFV-2 (CVE-2017-7564) 3、Advisory TFV-3 (CVE-2017-7563) 4、Advisory TFV-4 (CVE-2017-9607) 5、Adviso…...
LVS—DR集群的搭建
目录 lvs-dr模式工作原理: 搭建结构: 1、RS: 1)两台RS准备好httpd环境和测试文件 2)添加虚拟IP(vip)、添加访问本地vip的静态路由 并抑制ARP 2、DS: 1)安装ipvasadm…...
如何理解容量测试?如何做容量测试?
1、如何理解容量测试? 容量测试,是性能测试里的一部分,它的目的是测量系统的最大容量,为系统扩容、性能优化提供参考,节省成本投入,提高资源利用率。就是运用各种方法和工具在这种复杂的情况下去不断验证容…...
文件上传漏洞(webshell)
一、防护 1、防护 1、判断文件后缀,为图片的话才让上传成功。 2、解析文件内容(文件幻数)判断文件头和文件尾部是否一致 幻数 常见的 3、隐藏按钮(带上code唯一值) 4、二次渲染(类似拿着你的图片ÿ…...
.net几行代码音乐API各排行榜 热搜 入库
对比了几家大厂的音乐API的接口 这家相对规范些 现在开始从零开始 net6敏捷开发对接 入库吧 关键技术工具和思维 1 json 生成类 2 分析类 规划表设计3 sqlsuger codefirst 生成表 4 封装get post 连接5 类映射automapper6 sqlsuger 插入数据 1 json 生成类 宇宙 第 一的…...
使用gpt对对话数据进行扩增,对话数据扩增,数据增强
我们知道一个问题可以使用很多方式问,但都可以使用完全一样的回答,基于这个思路,我们可以很快的扩增我们的数据集。思路就是使用chatgpt或者gpt4生成类似问题,如下: 然后我们可以工程化这个过程,从而快速扩…...
算法练习工程1.2
题目要求: * 问题标题:删除有序数组中的重复项: * 题意说明: * 给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。 * …...
数字IC流片经历有多重要?怎样才能有流片机会?
都说拥有流片经验可以显示你在实际项目中的实践能力和对整个设计流程的了解程度,流片经历的重要性不言而喻。 什么是芯片流片 像流水线一样通过一系列工艺步骤制造芯片,这就是流片。在芯片制造过程中一般有两段时间可以叫作流片。 流片:英…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
