9.设计模式-COMPOSITE(组合)
一、模式定义与核心价值
组合模式是一种结构型设计模式,其核心目标是表示对象的部分-整体层次结构,使得客户端可以统一处理单个对象和组合对象。该模式通过树形结构组织对象,解决以下核心问题:
- 统一接口:消除叶子节点(简单对象)与容器节点(复合对象)的差异,使客户端无需区分操作类型
- 递归处理:支持对树形结构的深度遍历与批量操作(如渲染、删除、权限校验)
- 动态扩展:允许运行时动态添加/删除节点,构建复杂层次结构
工业级价值:
- 文件系统管理(文件与文件夹的统一操作)
- UI组件库开发(嵌套组件的统一渲染)
- 组织架构建模(部门与员工的层级关系)
二、模式组成与UML类图
核心角色:
- Component(抽象构件):
-
- 定义所有对象的统一接口(如
display()方法) - 声明管理子节点的方法(
add()/remove()),默认实现可抛出异常
- 定义所有对象的统一接口(如
- Leaf(叶子构件):
-
- 表示树形结构的末端节点(如单个文件、按钮)
- 不包含子节点,实现基础业务逻辑
- Composite(容器构件):
-
- 存储子构件集合(List/Map结构)
- 实现递归操作逻辑(如遍历渲染子节点)
UML类图:
classDiagram
class Component {
<<interface>>
+operation()
+add(Component)
+remove(Component)
+getChild(int)
}
class Leaf {
+operation()
}
class Composite {
-children: List<Component>
+operation()
+add(Component)
+remove(Component)
+getChild(int)
}
Component <|-- Leaf
Component <|-- Composite
Composite o-- Component

三、代码实现示例
场景:实现文件系统管理(文件与文件夹的统一操作)
1. 抽象构件(Component)
public abstract class FileSystemComponent {
protected String name;
public FileSystemComponent(String name) {
this.name = name;
}
// 基础操作
public abstract void display(int indent);
// 容器方法(默认不支持)
public void add(FileSystemComponent component) {
throw new UnsupportedOperationException();
}
public void remove(FileSystemComponent component) {
throw new UnsupportedOperationException();
}
}
2. 叶子构件(Leaf)
public class File extends FileSystemComponent {
public File(String name) {
super(name);
}
@Override
public void display(int indent) {
System.out.println(" ".repeat(indent) + "📄 " + name);
}
}
3. 容器构件(Composite)
public class Directory extends FileSystemComponent {
private List<FileSystemComponent> children = new ArrayList<>();
public Directory(String name) {
super(name);
}
@Override
public void display(int indent) {
System.out.println(" ".repeat(indent) + "📁 " + name);
children.forEach(child -> child.display(indent + 2));
}
@Override
public void add(FileSystemComponent component) {
children.add(component);
}
@Override
public void remove(FileSystemComponent component) {
children.remove(component);
}
}
4. 客户端调用
public class Client {
public static void main(String[] args) {
Directory root = new Directory("Project");
Directory src = new Directory("src");
src.add(new File("Main.java"));
src.add(new File("Utils.java"));
Directory test = new Directory("test");
test.add(new File("MainTest.java"));
root.add(src);
root.add(test);
root.display(0);
}
}
/* 输出:
📁 Project
📁 src
📄 Main.java
📄 Utils.java
📁 test
📄 MainTest.java
*/
四、工业级源码应用
- Java集合框架
-
java.util.Collections.unmodifiableList():返回的不可变列表本质是组合模式实现,统一处理单个元素与子列表
- Android UI系统
-
ViewGroup与View:ViewGroup作为容器构件管理子视图,Button/TextView作为叶子构件,通过onDraw()统一渲染
- Spring框架
-
CompositeCacheManager:组合多个缓存管理器(如Redis+Ehcache),提供统一的缓存操作接口
- 游戏开发引擎
-
- Unity的
GameObject:支持嵌套父子对象,通过Transform组件实现层级变换的统一管理
- Unity的
- 前端框架
-
- React的虚拟DOM树:组件树通过组合模式构建,
ReactElement作为抽象构件,DOM节点与自定义组件分别实现叶子/容器逻辑3****6
- React的虚拟DOM树:组件树通过组合模式构建,
五、模式优劣与选型建议
优势:
- 简化客户端逻辑:屏蔽对象类型差异,统一操作接口
- 支持递归处理:天然适合树形结构遍历(如权限校验、数据统计)
- 高扩展性:新增节点类型无需修改现有代码(开闭原则)
劣势:
- 接口污染风险:容器方法可能对叶子节点无意义(需权衡透明性与安全性)
- 性能损耗:深层次递归遍历可能影响效率(需结合缓存优化)
最佳实践:
- 优先透明性:在安全要求不高的场景,保持接口统一性
- 限制树深度:避免超深嵌套导致栈溢出(可改用迭代遍历)
- 结合访问者模式:解耦树操作与业务逻辑,提升可维护性
总结
组合模式通过树形结构组织与统一接口抽象,为复杂层次系统提供了优雅的解决方案。在Java生态中,该模式已深度融入集合框架、Spring等核心组件,并在前端、游戏引擎等领域展现强大生命力。掌握组合模式的关键在于准确识别树形结构需求,并在透明性与安全性之间找到平衡点,从而构建出灵活可扩展的层级管理系统。

浙公网安备 33010602011771号