【设计模式】组合模式(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教程 - 廖雪峰的官方网站

组合设计模式

相关推荐
Lam Tang9 小时前
APS 系列文章 08
java·代理模式
萧瑟余晖10 小时前
Java深入解析篇三十三之消息队列
java·开发语言
码匠许师傅10 小时前
【C++ 面试真题】聊聊 C++ 的序列容器
java·c++·面试
IT爱学堂10 小时前
尚硅谷Java+AI大模型应用开发革新版本 2025年3月
java·开发语言·人工智能
不爱编程的小九九11 小时前
小九源码-springboot004-springboot智能阅读推荐系统
java·spring boot·后端
SCandL15211 小时前
Docker的实战应用
java·docker·容器
AC赳赳老秦11 小时前
OpenClaw 多源采集公开行业数据:从原始信息到研究报告初稿的自动化实践
java·c语言·c++·python·php·deepseek·openclaw
Java成神之路-12 小时前
深入理解三大高频队列:ArrayDeque、LinkedList、PriorityQueue 方法、特性与场景选择
java
roman_日积跬步-终至千里12 小时前
【资源控制】自助查询的智能路由
java·大数据·数据库
步行cgn12 小时前
MyBatis Error evaluating expression ‘ids‘. Return value (3) was not iterable 错误详
java·后端