文章目录
-
- [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. 组合模式的结构
组合模式包含三个核心角色:
- Component(抽象构件)
定义系统各层次对象的共有方法和属性,可以预先定义一些默认行为和属性。
- Leaf(叶子节点)
叶子节点对象,其下再无分支,是系统层次遍历的最小单位。
- 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. 组合模式的优点
- 客户端使用简单
- 天然适合树结构
- 易于增加新节点类型
- 符合开闭原则
7. 组合模式的缺点
- 叶子和容器接口可能不完全一致
- 对类型限制不严格
- 容易被误用
8. 组合 vs 装饰 vs 外观
| 模式 | 关注点 |
|---|---|
| 组合 | 层级结构 |
| 装饰 | 功能叠加 |
| 外观 | 统一入口 |
9. JDK 中的组合模式
Java Swing
java
Container → JPanel → JButton
窗口、面板、按钮都继承自 Component,可以被统一操作。
10. 适用场景
适合使用
- 需要表示树形结构
- 想让整体和部分操作一致
- 目录、菜单、组织架构
组合模式正是应树形结构而生,所以组合模式的使用场景就是出现树形结构的地方。比如:文件目录显示,多级目录呈现等树形结构数据的操作。
不适合使用
- 结构不是层次型
- 节点类型差异太大
11. 一个经典误区
组合模式不是为了"套娃",而是为了"统一接口"。