当前位置: 首页 > news >正文

Java特性之设计模式【组合模式】

一、组合模式

概述

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

这种模式创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式

主要解决:它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦

何时使用:1、想表示对象的部分-整体层次结构(树形结构) 2、希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象

优缺点

优点:

  • 组合模式通过递归的形式遍历组合对象,使得对象可以无限层次地嵌套。这样可以更加灵活地表示复杂的结构,并能够方便地对整个结构进行操作
  • 通过组合模式,以统一的方式处理整体和部分,不需要关心当前操作的对象是叶节点还是组合节点,可以统一地进行操作

缺点:

  • 在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则

1. 各个角色介绍

1.1 组件(Component)

  • 定义了组合中所有对象的通用接口,可以是抽象类或接口。它声明了用于访问和管理子组件的方法,包括添加、删除、获取子组件等

1.2 叶子节点(Leaf)

  • 表示组合中的叶子节点对象,叶子节点没有子节点。它实现了组件接口的方法,但通常不包含子组件

1.3 复合节点(Composite)

  • 表示组合中的复合对象,复合节点可以包含子节点,可以是叶子节点,也可以是其他复合节点。它实现了组件接口的方法,包括管理子组件的方法

2. UML图

​ 我们有一个类 Component 对象作为所有对象的通用接口,然后 LeafComposite 分别实现该接口,并通过 Composite 构建非叶子节点和叶子节点,形成树状图,并以中序遍历的形式输出

在这里插入图片描述

3. 具体例子和代码

角色分配

  • Component:抽象组件
  • Leaf:叶子节点(叶子节点下,无组件,继承Component)
  • Composite:组合节点(继承Component)

3.1 抽象组件

  • Component
package com.vinjcent.prototype.composite;import io.swagger.annotations.ApiModelProperty;/*** @author vinjcent* @description 抽象组件* @since 2024/3/11 22:16*/
public abstract class Component {@ApiModelProperty("组件名称")protected String name;public Component(String name) {this.name = name;}/*** 组件操作*/public abstract void operation();/*** 为当前组件添加组件** @param component 需要添加的组件*/public abstract void add(Component component);/*** 移除某一组件** @param component 需要移除的组件*/public abstract void remove(Component component);/*** 根据下标获取子组件** @param index 下标* @return 下标对应组件*/public abstract Component getChild(int index);}

3.2 叶子节点

  • Leaf
package com.vinjcent.prototype.composite;/*** @author vinjcent* @description 叶子节点(叶子节点下,无组件)* @since 2024/3/11 22:20*/
public class Leaf extends Component {public Leaf(String name) {super(name);}public void operation() {System.out.println("Leaf " + name + " is performing operation.");}public void add(Component component) {// 在叶节点中无法添加子节点,可以选择抛出异常或忽略该操作throw new UnsupportedOperationException("Unsupported operation: add");}public void remove(Component component) {// 在叶节点中无法移除子节点,可以选择抛出异常或忽略该操作throw new UnsupportedOperationException("Unsupported operation: remove");}public Component getChild(int index) {// 叶节点没有子节点,返回null或抛出异常return null;}
}

3.3 组合节点

  • Composite
package com.vinjcent.prototype.composite;import io.swagger.annotations.ApiModelProperty;import java.util.ArrayList;
import java.util.List;/*** @author vinjcent* @description 组合节点* @since 2024/3/11 22:44*/
public class Composite extends Component {@ApiModelProperty("子节点")private List<Component> children;public Composite(String name) {super(name);children = new ArrayList<>();}@Overridepublic void operation() {System.out.println("Composite " + name + " is performing operation.");for (Component child : children) {child.operation();}}@Overridepublic void add(Component component) {children.add(component);}@Overridepublic void remove(Component component) {children.remove(component);}@Overridepublic Component getChild(int index) {return children.get(index);}
}

3.4 测试主函数

package com.vinjcent.prototype.composite;/*** @author vinjcent* @description 组合模式* @since 2024/3/11 22:51:07*/
public class Main {public static void main(String[] args) {// 根节点Component root = new Composite("Root");// 叶子节点1、2Component leaf1 = new Leaf("L. one");Component leaf2 = new Leaf("L. two");// 子节点1Component node1 = new Composite("N. one");Component leaf3 = new Leaf("L. three");// 子节点2Component node2 = new Composite("N. two");Component leaf4 = new Leaf("L. four");// 为子节点添加叶子节点node1.add(leaf3);node2.add(leaf4);// 为根节点添加子节点、叶子节点root.add(leaf1);root.add(leaf2);root.add(node1);root.add(node2);// 输出结果,相当于中序遍历root.operation();}}
  • 测试结果

在这里插入图片描述

4. 使用场景

  • 部分、整体场景,如树形菜单,文件、文件夹的管理
    在这里插入图片描述

相关文章:

  • 基于C++的一种字符串切分方法及示例代码
  • 升级版本彻底解决bootstrap-table-fixed-columns固定列后行对不齐问题
  • 滴滴 Flink 指标系统的架构设计与实践
  • 每天学习一个Linux命令之cat
  • rust开发100问?
  • antd5 虚拟列表原理(rc-virtual-list)
  • [剪藏] - 由哇哈哈和农夫山泉所想到的
  • OpenCV 图像重映射函数remap()实例详解
  • 游戏开发中的坑之十三 Lut贴图相关问题
  • 数据治理——滴滴大数据成本治理实践
  • ChromeDriver 122 版本为例 国内下载地址及安装教程
  • java零基础入门-Map遍历
  • 通过xlsx库解析读取excel表格内容
  • 现代化的轻量级Redis桌面客户端Tiny RDM
  • 加速 PyTorch 模型预测常见方法梳理
  • 收藏网友的 源程序下载网
  • 002-读书笔记-JavaScript高级程序设计 在HTML中使用JavaScript
  • DOM的那些事
  • JavaScript学习总结——原型
  • JS+CSS实现数字滚动
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • Python学习之路13-记分
  • React Transition Group -- Transition 组件
  • redis学习笔记(三):列表、集合、有序集合
  • Sass 快速入门教程
  • 浅谈JavaScript的面向对象和它的封装、继承、多态
  • 通过获取异步加载JS文件进度实现一个canvas环形loading图
  • Java总结 - String - 这篇请使劲喷我
  • 摩拜创始人胡玮炜也彻底离开了,共享单车行业还有未来吗? ...
  • !!java web学习笔记(一到五)
  • #laravel 通过手动安装依赖PHPExcel#
  • (保姆级教程)Mysql中索引、触发器、存储过程、存储函数的概念、作用,以及如何使用索引、存储过程,代码操作演示
  • (二)斐波那契Fabonacci函数
  • (附源码)计算机毕业设计ssm电影分享网站
  • (附源码)计算机毕业设计SSM智能化管理的仓库管理
  • (六)Hibernate的二级缓存
  • (论文阅读31/100)Stacked hourglass networks for human pose estimation
  • (译) 函数式 JS #1:简介
  • .NET 设计模式初探
  • .NET 中创建支持集合初始化器的类型
  • .NET企业级应用架构设计系列之结尾篇
  • @RequestParam,@RequestBody和@PathVariable 区别
  • []常用AT命令解释()
  • [AIGC] Redis基础命令集详细介绍
  • [AutoSar]BSW_OS 01 priority ceiling protocol(PCP)
  • [CareerCup] 14.5 Object Reflection 对象反射
  • [ESP32 IDF]web server
  • [Go WebSocket] 多房间的聊天室(五)用多个小锁代替大锁,提高效率
  • [HDU5685]Problem A
  • [linux学习]apt-get参数解析
  • [nlp] 损失缩放(Loss Scaling)loss sacle
  • [POI2007] ZAP-Queries (莫比乌斯反演)
  • [Python]—Linux Server 系统监控程序
  • [PyTorch][chapter 66][强化学习-值函数近似]
  • [SHELL]shell scripts笔记(1)