【设计模式】组合模式(Composite)详解

文章目录

    • [1. 引言:目录结构是怎么设计出来的?](#1. 引言:目录结构是怎么设计出来的?)
    • [2. 什么是组合模式](#2. 什么是组合模式)
      • [GoF 定义](#GoF 定义)
    • [3. 组合模式的核心思想](#3. 组合模式的核心思想)
    • [4. 组合模式的结构](#4. 组合模式的结构)
    • [5. 示例:文件系统](#5. 示例:文件系统)
      • [5.1 抽象组件](#5.1 抽象组件)
      • [5.2 叶子节点(文件)](#5.2 叶子节点(文件))
      • [5.3 容器节点(文件夹)](#5.3 容器节点(文件夹))
      • [5.4 客户端使用](#5.4 客户端使用)
    • [6. 组合模式的优点](#6. 组合模式的优点)
    • [7. 组合模式的缺点](#7. 组合模式的缺点)
    • [8. 组合 vs 装饰 vs 外观](#8. 组合 vs 装饰 vs 外观)
    • [9. JDK 中的组合模式](#9. JDK 中的组合模式)
      • [Java Swing](#Java Swing)
    • [10. 适用场景](#10. 适用场景)
    • [11. 一个经典误区](#11. 一个经典误区)
    • 参考

1. 引言:目录结构是怎么设计出来的?

在操作系统中,你会看到这样的结构:

plain 复制代码
/root
   ├── bin
   ├── usr
   │     ├── local
   │     └── share
   └── file.txt

这里有两种对象:

  • 目录(可以包含子目录和文件)
  • 文件(不能再包含东西)

但对用户来说:

它们都可以被"打开、删除、显示大小"。

如何让"文件"和"文件夹"在使用时看起来是一样的?

这正是组合模式要解决的问题。

只要你在设计"树形结构",就该想到组合模式。


2. 什么是组合模式

GoF 定义

将对象组合成树形结构以表示"部分-整体"的层次结构,使得用户对单个对象和组合对象的使用具有一致性。

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

一句话理解:

把"整体"和"部分"统一对待。


3. 组合模式的核心思想

组合模式解决的是:

如何让"容器对象"和"叶子对象"使用同一套接口。

它的本质是:

  • 把树结构隐藏在内部
  • 对外只暴露统一的操作接口

4. 组合模式的结构

组合模式包含三个核心角色:

  1. Component(抽象构件)

定义系统各层次对象的共有方法和属性,可以预先定义一些默认行为和属性。

  1. Leaf(叶子节点)

叶子节点对象,其下再无分支,是系统层次遍历的最小单位。

  1. Composite(容器节点)

定义树枝节点的行为,存储子节点,组合树枝节点和叶子节点形成一个树形结构。Composite本身就有合成的意思。


5. 示例:文件系统

5.1 抽象组件

java 复制代码
public abstract class FileComponent {
    public abstract void show();
}

5.2 叶子节点(文件)

java 复制代码
public class File extends FileComponent {

    private String name;

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

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

5.3 容器节点(文件夹)

java 复制代码
import java.util.ArrayList;
import java.util.List;

public class Folder extends FileComponent {

    private String name;
    private List<FileComponent> children = new ArrayList<>();

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

    public void add(FileComponent component) {
        children.add(component);
    }

    @Override
    public void show() {
        System.out.println("文件夹:" + name);
        for (FileComponent c : children) {
            c.show();
        }
    }
}

5.4 客户端使用

java 复制代码
File file1 = new File("a.txt");
File file2 = new File("b.txt");

Folder folder = new Folder("docs");
folder.add(file1);
folder.add(file2);

Folder root = new Folder("root");
root.add(folder);

root.show();

输出结果:

plain 复制代码
文件夹:root
文件夹:docs
文件:a.txt
文件:b.txt

客户端并不关心它是文件还是文件夹。


6. 组合模式的优点

  1. 客户端使用简单
  2. 天然适合树结构
  3. 易于增加新节点类型
  4. 符合开闭原则

7. 组合模式的缺点

  1. 叶子和容器接口可能不完全一致
  2. 对类型限制不严格
  3. 容易被误用

8. 组合 vs 装饰 vs 外观

模式 关注点
组合 层级结构
装饰 功能叠加
外观 统一入口

9. JDK 中的组合模式

Java Swing

java 复制代码
Container → JPanel → JButton

窗口、面板、按钮都继承自 Component,可以被统一操作。


10. 适用场景

适合使用

  • 需要表示树形结构
  • 想让整体和部分操作一致
  • 目录、菜单、组织架构

组合模式正是应树形结构而生,所以组合模式的使用场景就是出现树形结构的地方。比如:文件目录显示,多级目录呈现等树形结构数据的操作。

不适合使用

  • 结构不是层次型
  • 节点类型差异太大

11. 一个经典误区

组合模式不是为了"套娃",而是为了"统一接口"。


参考

组合模式 | 菜鸟教程

《图解设计模式》

组合 - Java教程 - 廖雪峰的官方网站

组合设计模式

相关推荐
JH30736 小时前
SpringBoot 优雅处理金额格式化:拦截器+自定义注解方案
java·spring boot·spring
Coder_Boy_7 小时前
技术让开发更轻松的底层矛盾
java·大数据·数据库·人工智能·深度学习
invicinble7 小时前
对tomcat的提供的功能与底层拓扑结构与实现机制的理解
java·tomcat
较真的菜鸟7 小时前
使用ASM和agent监控属性变化
java
黎雁·泠崖8 小时前
【魔法森林冒险】5/14 Allen类(三):任务进度与状态管理
java·开发语言
qq_12498707539 小时前
基于SSM的动物保护系统的设计与实现(源码+论文+部署+安装)
java·数据库·spring boot·毕业设计·ssm·计算机毕业设计
Coder_Boy_9 小时前
基于SpringAI的在线考试系统-考试系统开发流程案例
java·数据库·人工智能·spring boot·后端
Mr_sun.9 小时前
Day06——权限认证-项目集成
java
瑶山9 小时前
Spring Cloud微服务搭建四、集成RocketMQ消息队列
java·spring cloud·微服务·rocketmq·dashboard
abluckyboy9 小时前
Java 实现求 n 的 n^n 次方的最后一位数字
java·python·算法