Java设计模式:结构型模式→组合模式

Java 组合模式详解

1. 定义

组合模式(Composite Pattern)是一种结构型设计模式,它允许将对象组合成树形结构以表示“部分-整体”的层次。组合模式使得客户端能够以统一的方式对待单个对象和对象集合的一致性,有助于处理树形结构中双重角色的复杂性。

2. 基本思想

组合模式的基本思想在于通过一个统一的接口将所有的组件(即单个对象和组合对象)抽象为一种接口,这样在执行操作时,客户端就无需关心组件是单个对象还是组合对象。组合模式在设计时遵循了“合成复用原则”,可以通过简化操作和封装复杂性来提高代码的灵活性和可扩展性。

3. 基本原理

组合模式主要由以下部分构成:

  • 组件接口(Component):定义了树形结构中所有对象的接口,包括叶子节点(单个对象)和树枝节点(组合对象)的方法。
  • 叶子节点(Leaf):实现组件接口的具体类,表示树结构中的基本元素,不能包含子节点。
  • 树枝节点(Composite):同样实现组件接口,属于容器类型的对象,可以包含叶子节点或其他树枝节点。
    在这里插入图片描述

更多实用资源:

http://sj.ysok.net/jydoraemon 访问码:JYAM

4. 实现方式

4.1 基本实现

4.1.1 组件接口

定义一个组件接口,描述基本的操作:

public interface Component {void operation();
}
4.1.2 叶子节点类

实现叶子节点,表示树的基本元素:

public class Leaf implements Component {private String name;public Leaf(String name) {this.name = name;}@Overridepublic void operation() {System.out.println("Leaf: " + name);}
}
4.1.3 树枝节点类

实现树枝节点,能够包含叶子和其他树枝:

import java.util.ArrayList;
import java.util.List;public class Composite implements 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);}@Overridepublic void operation() {System.out.println("Composite: " + name);for (Component child : children) {child.operation();}}
}
4.1.4 客户端代码

下面是客户端代码,展示如何使用组合模式:

public class Client {public static void main(String[] args) {Composite root = new Composite("Root");Leaf leaf1 = new Leaf("Leaf 1");Leaf leaf2 = new Leaf("Leaf 2");Composite composite1 = new Composite("Composite 1");Leaf leaf3 = new Leaf("Leaf 3");composite1.add(leaf3);root.add(leaf1);root.add(leaf2);root.add(composite1);root.operation(); // This will invoke the operation method for the whole structure}
}

4.2 代码分析

  • 组件接口(Component):定义了所有组件都必需实现的接口。这样,客户端可以使用统一的方式来操作。
  • 叶子节点(Leaf):实现组件接口,表示不能再加入子节点的对象,定义具体的业务逻辑。
  • 树枝节点(Composite):实现组件接口,持有所有子组件并实现对它们的管理,包括添加和移除子组件的功能。
  • 客户端:通过创建组合结构来组织组件,使得用户可以轻松操作复杂的对象结构。

5. 工作流程

  1. 定义组件接口:创建一个接口,提供所有组件需要实现的方法。
  2. 创建叶子节点类:实现组件接口,定义基本操作和具体业务。
  3. 创建树枝节点类:实现组件接口,管理子组件,包括添加、删除和操作子组件。
  4. 客户端使用组合:通过创建组合对象来添加叶子节点和其他树枝节点,统一管理整个结构。

6. 变种

  1. 递归组合:可以实现更复杂的组合,通过子组合继续组合形成多层结构。
  2. 安全组合:结合访问控制,只允许特定对组合的访问方式,以控制树的完整性。

7. 实际应用

组合模式在实际应用中广泛存在,以下是一些典型应用场景:

  1. 文件系统:文件和目录之间的关系可以用组合模式表示,目录可以包含文件和其它目录。
  2. GUI 组件:在图形用户界面中,组件和容器(如窗口、面板)之间的关系可以用组合模式管理。
  3. 组织结构:处理公司或团队的组织结构,部门(树枝节点)可以包含员工(叶子节点)、其他部门(树枝节点)等。

8. 使用场景

使用组合模式的场景包括:

  • 当客户端需要统一处理单个对象和组合对象时。
  • 当你需要用树形结构表现对象的组合关系时。
  • 当你希望能够增加新的叶子和组合节点而无须改变现有代码时。

9. 优缺点

优点

  1. 简化客户端代码:客户端通过统一的接口与组件交互,无需关心树的结构。
  2. 灵活性:可以轻松添加新叶子和新的组合、维持已有结构。
  3. 高层次的透明性:客户端可以一致地对待树的节点和组合。

缺点

  1. 实现复杂性:逻辑上的复杂性可能会增加,特别是在处理组合时。
  2. 性能问题:对于非常深的组合结构,可能会造成性能问题,推迟操作实现。

10. 最佳实践

  1. 避免过度组合:组合结构应适度,避免组合生成过长的结构,减低可维护性。
  2. 使用统一接口:确保所有组件实现统一的接口,以增加灵活性和可扩展性。
  3. 固定接口设计:组件接口应尽量保持稳定以避免频繁的修改。

11. 注意事项

  1. 管理树的变化:设计树的结构时,避免频繁修改或调整结构,以防引入逻辑错误。
  2. 处理复杂性:注意过度设计,简单结构需保持简单。
  3. 性能监测:考虑树的深度和广度,在性能敏感的场景中小心使用。

12. 常见的误区

  • 组合模式仅适用于树形结构:实际上,它可以用于其他潜在的组合关系,具备组织的灵活性。
  • 认为组合模式只为复杂系统设计:组合模式同样适用于简单的、几乎不复杂的系统结构,以保持强一致性。

13. 常见问题

  • 如何判断使用组合模式呢?

    • 通常在有“部分-整体”结构需要处理时,就考虑使用组合模式。
  • 组合模式的核心组成部分是什么?

    • 树形结构的组成部分有组件接口、叶子节点类、树枝节点类和客户端。
  • 组合模式如何处理节点的状态变化?

    • 通过组件接口中的方法定义所需的状态变更,树的任何节点均可变化并影响整个结构。

14. 总结

组合模式是一种强大的设计模式,它简化了树形结构中复杂对象的管理与交互。通过建立一个统一接口,使得客户端能够轻松操作组合的对象,增强了代码的可读性、可维护性和扩展性。在实际开发中,合理运用组合模式不仅能够提升软件的质量,还能有效管理复杂的业务需求。通过对组合模式的掌握与经验积累,开发者能更好地设计出灵活、易扩展的应用程序。

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

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

相关文章

多线程-线程池的使用

1. 线程池 1.1 线程状态介绍 当线程被创建并启动以后&#xff0c;它既不是一启动就进入了执行状态&#xff0c;也不是一直处于执行状态。线程对象在不同的时期有不同的状态。那么 Java 中的线程存在哪几种状态呢&#xff1f;Java 中的线程 状态被定义在了 java.lang.Thread.…

JavaSE第十一天——集合框架Collection

一、List接口 List接口是一个有序的集合&#xff0c;允许元素有重复&#xff0c;它继承了Collection接口&#xff0c;提供了许多额外的功能&#xff0c;比如基于索引的插入、删除和访问元素等。 常见的List接口的实现类有ArrayList、LinkedList和Vector。 List接口的实现类 …

Flutter_学习记录_导航和其他

Flutter 的导航页面跳转&#xff0c;是通过组件Navigator 和 组件MaterialPageRoute来实现的&#xff0c;Navigator提供了很多个方法&#xff0c;但是目前&#xff0c;我只记录我学习过程中接触到的方法&#xff1a; Navigator.push(), 跳转下一个页面Navigator.pop(), 返回上一…

基于 AWS SageMaker 对 DeepSeek-R1-Distilled-Llama-8B 模型的精调与实践

在当今人工智能蓬勃发展的时代&#xff0c;语言模型的性能优化和定制化成为研究与应用的关键方向。本文聚焦于 AWS SageMaker 平台上对 DeepSeek-R1-Distilled-Llama-8B 模型的精调实践&#xff0c;详细探讨这一过程中的技术细节、操作步骤以及实践价值。 一、实验背景与目标 …

arkui-x跨平台与android java联合开发

华为鸿蒙系统采用的是arkts&#xff0c;支持跨平台crossplatform 即前端为arkts&#xff0c;arkui-x框架&#xff0c;后端为其他的语言框架。 本篇示例后端采用的是java&#xff0c;android studio工程。 主要方式是前端鸿蒙完成界面元素、布局等效果&#xff0c;后面androi…

机器人基础深度学习基础

参考&#xff1a; &#xff08;1&#xff09;【具身抓取课程-1】机器人基础 &#xff08;2&#xff09;【具身抓取课程-2】深度学习基础 1 机器人基础 从平面二连杆理解机器人学 正运动学&#xff1a;从关节角度到末端执行器位置的一个映射 逆运动学&#xff1a;已知末端位置…

k8s支持自定义field-selector spec.hostNetwork过滤

好久没写博客啦&#xff0c;年前写一个博客就算混过去啦&#x1f602; 写一个小功能&#xff0c;对于 Pod&#xff0c;在没有 label 的情况下&#xff0c;支持 --field-selector spec.hostNetwork 查询 Pod 是否为 hostNetwork 类型&#xff0c;只为了熟悉 APIServer 是如何构…

5分钟带你获取deepseek api并搭建简易问答应用

目录 1、获取api 2、获取base_url和chat_model 3、配置模型参数 方法一&#xff1a;终端中临时将加入 方法二&#xff1a;创建.env文件 4、 配置client 5、利用deepseek大模型实现简易问答 deepseek-v3是截止博文撰写之日&#xff0c;无论是国内还是国际上发布的大模型中…

RDMA 工作原理 | 支持 RDMA 的网络协议

注&#xff1a;本文为 “RDMA” 相关文章合辑。 英文引文机翻未校。 图片清晰度受引文所限。 Introduction to Remote Direct Memory Access (RDMA) Written by: Dotan Barak on March 31, 2014.on February 13, 2015. What is RDMA? 什么是 RDMA&#xff1f; Direct me…

【AutoSar】汽车诊断标准协议UDS详解

目录 一、基本概念二、UDS诊断协议2.1 诊断服务的概念2.2常用的诊断服务2.2.1 诊断会话控制服务&#xff08;10服务&#xff09;2.2.2 会话访问0x27服务2.2.3 用于读写的DID的0x22/0x2E服务 一、基本概念 车辆的诊断需要有Tester端和ECU段通过应答的方式进行通信&#xff0c;他…

wx043基于springboot+vue+uniapp的智慧物流小程序

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…

实践网络安全:常见威胁与应对策略详解

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 引言 在数字化转型的浪潮中&#xff0c;网络安全的重要性已达到前所未有的高度。无论是个人用户、企业&#xff0c;还是政府机构…

深入 Rollup:从入门到精通(三)Rollup CLI命令行实战

准备阶段&#xff1a;初始化项目 初始化项目&#xff0c;这里使用的是pnpm&#xff0c;也可以使用yarn或者npm # npm npm init -y # yarn yarn init -y # pnpm pnpm init安装rollup # npm npm install rollup -D # yarn yarn add rollup -D # pnpm pnpm install rollup -D在…

快速分析LabVIEW主要特征进行判断

在LabVIEW中&#xff0c;快速分析程序特征进行判断是提升开发效率和减少调试时间的重要技巧。本文将介绍如何高效地识别和分析程序的关键特征&#xff0c;从而帮助开发者在编写和优化程序时做出及时的判断&#xff0c;避免不必要的错误。 ​ 数据流和并行性分析 LabVIEW的图形…

【AI】【本地部署】OpenWebUI的升级并移植旧有用户信息

【背景】 OpenWebUI的版本升级频率很高&#xff0c;并会修改旧版本的Bug&#xff0c;不过对于已经在使用的系统&#xff0c;升级后现有用户信息都会丢失&#xff0c;于是研究如何在升级后将现有的用户信息移植到升级后版本。 【准备工作】 OpenWebUI的升级步骤在Docker中有现…

【阅读笔记】New Edge Diected Interpolation,NEDI算法,待续

一、概述 由Li等提出的新的边缘指导插值(New Edge—Di-ected Interpolation&#xff0c;NEDI)算法是一种具有良好边缘保持效果的新算法&#xff0c;它利用低分辨率图像与高分辨率图像的局部协方差问的几何对偶性来对高分辨率图像进行自适应插值。 2001年Xin Li和M.T. Orchard…

DeepSeek-R1:开源Top推理模型的实现细节、使用与复现

核心观点 ● 直接用强化学习就可以让模型获得显著的推理能力&#xff0c;说明并不一定需要SFT才行。 ● 强化学习并不一定需要复杂的奖励模型&#xff0c;使用简单的规则反而取得意想不到的效果。 ● 通过知识蒸馏让小模型一定程度上也有推理能力&#xff0c;甚至在某些场景下…

Unity游戏(Assault空对地打击)开发(1) 创建项目和选择插件

目录 前言 创建项目 插件导入 地形插件 前言 这是游戏开发第一篇&#xff0c;进行开发准备。 创作不易&#xff0c;欢迎支持。 我的编辑器布局是【Tall】&#xff0c;建议调整为该布局&#xff0c;如下。 创建项目 首先创建一个项目&#xff0c;过程略&#xff0c;名字请勿…

汽车网络信息安全-ISO/SAE 21434解析(中)

目录 第七章-分布式网络安全活动 1. 供应商能力评估 2. 报价 3. 网络安全职责界定 第八章-持续的网络安全活动 1. 网路安全监控 2. 网络安全事件评估 3. 漏洞分析 4. 漏洞管理 第九章-概念阶段 1. 对象定义 2. 网路安全目标 3. 网络安全概念 第十章 - 产品开发 第十…

K8S极简教程(4小时快速学会)

1. K8S 概览 1.1 K8S 是什么 K8S官网文档&#xff1a;https://kubernetes.io/zh/docs/home/ 1.2 K8S核心特性 服务发现与负载均衡&#xff1a;无需修改你的应用程序即可使用陌生的服务发现机制。存储编排&#xff1a;自动挂载所选存储系统&#xff0c;包括本地存储。Secret和…