设计模式 结构型 组合模式(Composite Pattern)与 常见技术框架应用 解析

在这里插入图片描述

组合模式(Composite Pattern)是一种结构型设计模式,它允许你将对象组合成树形结构来表示“部分-整体”的层次结构。通过这种模式,客户端可以一致地处理单个对象和对象组合。

在软件开发中,我们经常会遇到处理对象的层次结构的情况。例如,在图形系统中,有简单的图形(如直线、圆),也有由这些简单图形组合而成的复杂图形;在文件系统中,有文件和文件夹,文件夹可以包含文件和其他文件夹。组合模式就是为了方便地处理这种“部分 - 整体”的层次结构而诞生的。

一、核心思想

核心思想是让客户能够透明地使用单独的个体或者由多个个体组成的群体。无论是一个单一的对象还是一个复杂对象的集合,对于客户端来说,它们都是一样的,这样就可以简化客户端代码。

二、定义与结构

  • 定义:组合模式允许你将对象组合成树形结构来表现“部分 - 整体”的层次结构。组合能让客户端以一致的方式处理个别对象以及对象组合。
  • 结构
    • Component(抽象组件):这是组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。它可以是抽象类或者接口,定义了叶子节点和组合节点都需要实现的操作,比如添加(add)、删除(remove)和获取子节点(getChild)等方法。
    • Leaf(叶子节点):叶子节点对象是组合的最底层对象,它没有子节点。它实现了组件接口中定义的操作,但对于涉及子节点的操作(如添加和删除子节点)通常不做任何处理或者抛出异常,因为叶子节点没有子节点。
    • Composite(组合节点):组合节点表示包含子节点的节点对象。它实现了组件接口,并且在内部维护一个子组件的集合。它的主要职责是实现对子组件的添加、删除和遍历等操作,并且在执行某些操作时,会将请求递归地传递给它的子组件。

三、角色

1、抽象组件(Component)

职责

  • 定义了组合中对象的接口,这个接口可以被叶子节点和组合节点共同实现。
  • 可以包含一些默认的方法实现,这些实现对于叶子节点和组合节点可能有不同的行为。

示例代码(以图形绘制系统为例)

// 抽象组件
interface Graphic {
    void draw();
}

这里定义了一个Graphic接口,draw方法是所有图形(无论是简单图形还是复杂图形组合)都需要实现的绘制方法。

2、叶子节点(Leaf)

职责

  • 表示树形结构中的叶子对象,没有子节点。
  • 实现抽象组件接口中定义的方法,但是对于和子节点相关的操作(如添加、删除子节点)通常不实现或者抛出异常。

示例代码(以图形绘制系统为例)

// 叶子节点 - 圆形
class Circle implements Graphic {
    @Override
    public void draw() {
        System.out.println("绘制圆形");
    }
}
// 叶子节点 - 矩形
class Rectangle implements Graphic {
    @Override
    public void draw() {
        System.out.println("绘制矩形");
    }
}

CircleRectangle类是叶子节点,它们实现了Graphic接口的draw方法,用于绘制自身,但是它们没有子节点相关的操作,因为它们本身就是最基本的图形单元。

3、组合节点(Composite)

职责

  • 表示包含子节点的对象,维护一个子组件的集合。
  • 实现抽象组件接口中的方法,并且在这些方法中通常会递归地调用子组件的相应方法。
  • 提供管理子组件的方法,如添加、删除和获取子组件。

示例代码(以图形绘制系统为例)

// 组合节点
class ComplexGraphic implements Graphic {
    private List<Graphic> graphics = new ArrayList<>();
    public void add(Graphic graphic) {
        graphics.add(graphic);
    }
    @Override
    public void draw() {
        for (Graphic graphic : graphics) {
            graphic.draw();
        }
    }
}

ComplexGraphic是组合节点,它内部有一个List来保存子图形。add方法用于添加子图形,draw方法会遍历所有子图形并调用它们的draw方法,从而实现复杂图形的绘制。

四、实现步骤及代码示例

以图形绘制系统为例:

1. 步骤一:定义抽象组件(Graphic)

如上述代码所示,定义Graphic接口,其中包含draw方法。这是所有图形(简单图形和复杂图形组合)的公共接口。

2. 步骤二:创建叶子节点(Circle和Rectangle)

分别创建CircleRectangle类实现Graphic接口。在draw方法中实现各自的绘制逻辑,例如Circle类的draw方法输出“绘制圆形”,Rectangle类的draw方法输出“绘制矩形”。

3. 步骤三:构建组合节点(ComplexGraphic)

  • 创建ComplexGraphic类实现Graphic接口。
  • 定义一个List<Graphic>类型的成员变量,用于存储子图形。
  • 实现add方法,用于将子图形添加到列表中。
  • 实现draw方法,通过遍历列表中的子图形并调用它们的draw方法来绘制复杂图形。

4. 步骤四:使用组合模式

public class Main {
    public static void main(String[] args) {
        // 创建一个复杂图形
        ComplexGraphic complexGraphic = new ComplexGraphic();
        // 添加一个圆形和一个矩形到复杂图形中
        complexGraphic.add(new Circle());
        complexGraphic.add(new Rectangle());
        // 绘制复杂图形
        complexGraphic.draw();
    }
}

main方法中,首先创建一个ComplexGraphic对象,然后添加一个Circle和一个Rectangle作为子图形,最后调用draw方法来绘制这个复杂图形。客户端代码只需要调用draw方法,不需要区分是简单图形还是复杂图形组合,这体现了组合模式的统一处理方式。

五、常见技术框架应用

1、在Java AWT/Swing中的应用

组件与容器关系

  • 在Java的图形用户界面(GUI)编程中,Container类(组合节点)和Component类(叶子节点或者其他组合节点)的关系符合组合模式。Container类可以包含多个Component
  • 例如,JPanel是一个ContainerJButtonJLabelComponent

示例代码(简单的Swing界面布局)

import javax.swing.*;
import java.awt.*;

public class SwingCompositeExample {
    public static void main(String[] args) {
        JFrame frame = new JFrame("组合模式在Swing中的应用");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(300, 300);

        JPanel panel = new JPanel();
        panel.setLayout(new FlowLayout());

        JButton button1 = new JButton("按钮1");
        JButton button2 = new JButton("按钮2");

        panel.add(button1);
        panel.add(button2);

        frame.add(panel);
        frame.setVisible(true);
    }
}

在这个示例中,JFrame(顶级窗口,类似于组合模式中的一个组合节点)包含JPanel(组合节点),JPanel又包含JButton(叶子节点)。当JFrame被显示时,它会递归地布局和显示所有包含的组件,这和组合模式中组合节点操作子节点的方式类似。

2、文件系统的应用

文件与文件夹的树形结构

  • 文件系统是组合模式的典型例子。文件可以看作是叶子节点,文件夹可以看作是组合节点。文件夹可以包含文件和其他文件夹。

示例代码(简单的文件系统遍历模拟)

import java.util.ArrayList;
import java.util.List;

// 抽象组件 - 文件系统元素
interface FileSystemElement {
    void display();
}

// 叶子节点 - 文件
class File implements FileSystemElement {
    private String name;

    public File(String name) {
        this.name = name;
    }

    @Override
    public void display() {
        System.out.println("文件: " + name);
    }
}

// 组合节点 - 文件夹
class Directory implements FileSystemElement {
    private String name;
    private List<FileSystemElement> elements = new ArrayList<>();

    public Directory(String name) {
        this.name = name;
    }

    public void add(FileSystemElement element) {
        elements.add(element);
    }

    @Override
    public void display() {
        System.out.println("文件夹: " + name);
        for (FileSystemElement element : elements) {
            element.display();
        }
    }
}

public class FileSystemCompositeExample {
    public static void main(String[] args) {
        Directory root = new Directory("根目录");
        File file1 = new File("文件1");
        File file2 = new File("文件2");
        Directory subDir = new Directory("子目录");
        File subFile = new File("子文件");

        root.add(file1);
        root.add(file2);
        root.add(subDir);
        subDir.add(subFile);

        root.display();
    }
}

在这个示例中,定义了FileSystemElement接口,File类实现了文件叶子节点,Directory类实现了文件夹组合节点。通过display方法来展示文件或文件夹的信息,文件夹的display方法会递归地展示其包含的所有文件和文件夹。

3、UI组件树

在React中,组合模式被广泛应用于构建UI组件树:

// React Component Example
function Leaf(props) {
  return <div>{props.text}</div>;
}

class Composite extends React.Component {
  render() {
    return (
      <div>
        {this.props.children.map((child, index) => (
          <div key={index}>{child}</div>
        ))}
      </div>
    );
  }
}

// Usage in App.js
function App() {
  return (
    <Composite>
      <Leaf text="Child 1" />
      <Leaf text="Child 2" />
    </Composite>
  );
}

六、应用场景

  • 树形结构数据表示:当需要表示树形结构的数据,如组织结构图、文件系统、菜单系统等,组合模式可以很好地对这种结构进行建模。
  • 统一处理对象和对象组合:如果客户端需要以相同的方式处理单个对象和对象组合,组合模式可以提供统一的接口。例如,在图形绘制系统中,无论是绘制单个图形还是由多个图形组成的复杂图形,都可以使用相同的绘制方法。
  • 部分 - 整体层次关系的操作:对于具有部分 - 整体层次关系的对象,并且需要对这种关系进行动态的添加、删除和遍历操作时,组合模式非常适用。比如在一个软件系统中,模块可以包含子模块,并且可以动态地添加或删除子模块。
  • 图形界面构建

七、优缺点

优点

  1. 简化客户端代码:客户端可以统一地使用组合结构中的所有对象,不需要区分是单个对象还是组合对象,大大简化了客户端的代码结构。
  2. 易于添加新类型的组件:无论是添加新的叶子节点还是新的组合节点,只要它们实现了抽象组件接口,就可以很容易地集成到现有的组合结构中。
  3. 方便进行递归操作:由于组合模式天然地形成了树形结构,对于树形结构的递归操作(如遍历、计算等)变得更加容易实现,代码更加清晰。

缺点

  1. 设计复杂度过高:对于简单的层次结构,使用组合模式可能会使设计变得过于复杂。因为需要引入抽象组件、叶子节点和组合节点等多个角色,增加了代码的复杂性。
  2. 限制组件接口通用性:为了使叶子节点和组合节点都能实现抽象组件接口,接口的设计可能会受到一定的限制。有时候可能需要在接口中包含一些对于叶子节点没有实际意义的方法(如添加子节点的方法对于叶子节点通常没有意义)。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

抢先体验:人大金仓数据库管理系统KingbaseES V9 最新版本 CentOS 7.9 部署体验

一、简介 KingbaseES 是中国人大金仓信息技术股份有限公司自主研发的一款通用关系型数据库管理系统&#xff08;RDBMS&#xff09;。 作为国产数据库的杰出代表&#xff0c;它专为中国市场设计&#xff0c;广泛应用于政府、金融、能源、电信等关键行业&#xff0c;以高安全性…

Linux驱动开发(17):输入子系统–电阻触摸驱动实验

有关电阻触摸的基础知识内容可以参考野火STM32相关教程&#xff0c;这里只介绍电阻触摸驱动的相关内容。与一般的微处理器 不同&#xff0c;本节使用的imx6ull内自带触摸屏控制器&#xff0c;只需要把电阻触摸屏的信号线接到对应的IO即可&#xff0c;通过配置imx6ull 触摸屏控制…

8、RAG论文笔记(Retrieval-Augmented Generation检索增强生成)

RAG论文笔记 1、 **研究背景与动机**2、方法概述3、RAG 模型架构3.1总体架构3.2 Generator&#xff08;生成器&#xff09;3.3 检索器&#xff08;Retriever&#xff09;3.4训练&#xff08;Training&#xff09;3.5**解码方法**&#xff08;求近似 &#xff09;3.6微调的参数 …

简易CPU设计入门:通用寄存器的读写

项目代码下载 请大家首先准备好本项目所用的源代码。如果已经下载了&#xff0c;那就不用重复下载了。如果还没有下载&#xff0c;那么&#xff0c;请大家点击下方链接&#xff0c;来了解下载本项目的CPU源代码的方法。 下载本项目代码 准备好了项目源代码以后&#xff0c;我…

【动手学电机驱动】STM32-MBD(3)Simulink 状态机模型的部署

STM32-MBD&#xff08;1&#xff09;安装 Simulink STM32 硬件支持包 STM32-MBD&#xff08;2&#xff09;Simulink 模型部署入门 STM32-MBD&#xff08;3&#xff09;Simulink 状态机模型的部署 【动手学电机驱动】STM32-MBD&#xff08;3&#xff09;Simulink 状态机模型部署…

Linux运维相关基础知识(二)

系列文章目录 Linux常用命令 linux 账号管理与权限设定 Linux运维相关基础知识 文章目录 系列文章目录前言1. 自动任务执行at 与 atdcrontab 与 crond 2. SELinuxtty多任务管理与进程管理相关的命令/proc/* 文件的意义SELinux 3. 守护进程早期SystemV的init管理行为中daemon…

K8s集群平滑升级(Smooth Upgrade of K8S Cluster)

简介&#xff1a; Kubernetes ‌ &#xff08;简称K8s&#xff09;是一个开源的容器编排和管理平台&#xff0c;由Google开发并维护。它最初是为了解决谷歌内部大规模容器管理的问题而设计的&#xff0c;后来在2014年开源&#xff0c;成为云原生技术的核心组成部分。‌‌1 K8…

党员学习交流平台

本文结尾处获取源码。 本文结尾处获取源码。 本文结尾处获取源码。 一、相关技术 后端&#xff1a;Java、JavaWeb / Springboot。前端&#xff1a;Vue、HTML / CSS / Javascript 等。数据库&#xff1a;MySQL 二、相关软件&#xff08;列出的软件其一均可运行&#xff09; I…

uniapp--HBuilder开发

提示&#xff1a;本文为学习内容&#xff0c;若有错误&#xff0c;请联系作者&#xff0c;谦虚受教。 文章目录 前言一、下载HBuilder二、添加modbus相关库1.下载nodejs2.下载modbus库3.项目添加modbus库 三、HBuilder相关功能语句1.文件夹说明2.消息信息框3.开关按钮4.选中按钮…

GraphRAG实践:neo4j试用

文章目录 前言欢迎界面示例数据库使用大模型生成查询语句总结 前言 上回说道&#xff0c;我们使用docker部署了一个neo4j。 我们现在对它进行一些试用。 欢迎界面 在浏览器中输入http://localhost:7474/ 输入对应的东西&#xff0c;点击connect 现在咱的数据库里什么都没有…

两种分类代码:独热编码与标签编码

目录 一、说明 二、理解分类数据 2.1 分类数据的类型&#xff1a;名义数据与序数数据 2.2 为什么需要编码 三、什么是独热编码&#xff1f; 3.1 工作原理&#xff1a;独热编码背后的机制 3.2 应用&#xff1a;独热编码的优势 四、什么是标签编码&#xff1f; 4.1 工作原理&…

【AWS SDK PHP】This operation requests `sigv4a` auth schemes 问题处理

使用AWS SDK碰到的错误&#xff0c;其实很简单&#xff0c;要装个扩展库 保持如下 Fatal error: Uncaught Aws\Auth\Exception\UnresolvedAuthSchemeException: This operation requests sigv4a auth schemes, but the client currently supports sigv4, none, bearer, sigv4-…

限时特惠,香港服务器,低至53元/年

家人们谁懂啊&#xff01;香港服务器这价格简直逆天了&#xff0c;居然比内地的还便宜&#xff01;就拿阿里云来说&#xff0c;人家最低配置的服务器&#xff0c;价格都很难做到这么亲民。 最低配的就不说了&#xff0c;2 核 4G 的配置&#xff0c;应对日常业务稳稳当当&#x…

USB子系统学习(一)USB电气信号

文章目录 1、声明2、USB协议概述3、USB电气信号3.1、USB基础概念3.1.1、低速/全速信号电平3.1.2、高速信号电平 3.2、学习目标3.3、设备断开与连接3.3.1、连接3.3.2、断开 3.4、复位3.5、设备速率识别3.5.1、低速/全速3.5.2、高速 3.6、数据信号3.6.1、低速/全速的SOP和EOP3.6.…

【机器学习篇】从新手探寻到算法初窥:数据智慧的开启之门

文章目录 【机器学习篇】从新手探寻到算法初窥&#xff1a;数据智慧的开启之门前言一、什么是机器学习&#xff1f;二、机器学习的基本类型1. 监督学习&#xff08;Supervised Learning&#xff09;2. 无监督学习&#xff08;Unsupervised Learning&#xff09;3. 半监督学习&a…

SQL-Server链接服务器访问Oracle数据

SQL Server 链接服务器访问 Oracle 离线安装 .NET Framework 3.5 方法一&#xff1a;使用 NetFx3.cab 文件 下载 NetFx3.cab 文件&#xff0c;并将其放置在 Windows 10 系统盘的 C:Windows 文件夹中。 以管理员身份运行命令提示符&#xff0c;输入以下命令并回车&#xff1a; …

【C++】矩阵转置问题详解与优化

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;题目解析&#x1f4af;第一种实现方式&#xff1a;我的初始做法实现思路优缺点分析 &#x1f4af;第二种实现方式&#xff1a;我的优化做法实现思路优缺点分析 &#x1f4a…

比QT更高效的一款开源嵌入式图形工具EGT-Ensemble Graphics Toolkit

文章目录 EGT-Ensemble Graphics Toolkit介绍EGT具备非常高的图形渲染效率EGT采用了非常优秀的开源2D图形处理引擎-Cairo开源2D图形处理引擎Cairo的优势Cairo 2D图像引擎的性能Cairo 2D图像引擎的实际应用案例彩蛋 - 开源EDA软件KiCAD也在使用Cairo EGT高效的秘诀还有哪些Cairo…

信息系统管理工程师教程第2版(2024年最新版)

信息系统管理工程师教程第2版 目录 第 1 章 信息化发展 第 2 章 信息技术发展 第 3 章 信息系统架构 第 4 章 信息系统治理 第 5 章 信息技术服务管理 第 6 章 软件开发过程管理 第 7 章 系统集成实施管理 第 8 章 信息系统运维管理 第 9 章 云服务及其运营…

Science Robotics让软机器人“活”得更久的3D打印!

软机器人硬件在医疗、探索无结构环境等领域有广泛应用&#xff0c;但其生命周期有限&#xff0c;导致资源浪费和可持续性差。软机器人结合软硬组件&#xff0c;复杂组装和拆卸流程使其难以维修和升级。因此&#xff0c;如何延长软机器人的生命周期并提高其可持续性成为亟待解决…