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

组合设计模式

相关推荐
胖虎12 小时前
iOS中的设计模式(十)- 中介者模式(从播放器场景理解中介者模式)
设计模式·中介者模式·解耦·ios中的设计模式
怦怦蓝2 小时前
IDEA 项目打印日志全攻略:从基础使用到高级配置
java·开发语言·debug
Stream_Silver2 小时前
高效并行测试:在IDEA中同时运行多个参数化测试配置(idea2019如何在同一个项目运行多次)
java·ide·intellij-idea
BD_Marathon2 小时前
搭建MyBatis框架之创建mapper接口(四)
java·前端
kaico20182 小时前
ConcurrentHashMap源码分析
java
刀法孜然2 小时前
23种设计模式 3 行为型模式 之3.6 mediator 中介者模式
设计模式·中介者模式
虫小宝2 小时前
企业微信API接口对接中Java后端的模拟测试(Mock)与单元测试实战技巧
java·单元测试·企业微信
Tim_Van2 小时前
彻底解决:80 端口 GET/POST 正常,PUT 却报 ERR_CONNECTION_RESET?
java·vue.js·spring boot·ruoyi·若依
元媛媛2 小时前
UiPath |5个基础自动化场景
android·java·自动化