CHARLIE SAYS

查理如是说
DATE 2026-08-24
THEME
SERIES / DESIGN_PATTERNS / P-105 · 设计模式

设计模式 011:组合(Composite)

意图

将对象组合成树形结构来表示”整体/部分”层次关系,允许用户以相同的方式处理单独对象和组合对象。

类图

组件(Component)类是组合类(Composite)和叶子类(Leaf)的父类,可以把组合类看成是树的中间节点。组合对象拥有一个或者多个组件对象,因此组合对象的操作可以委托给组件对象去处理,而组件对象可以是另一个组合对象或者叶子对象。

classDiagram
    class Component {
        <<abstract>>
        #name String
        +print() void
        +print(level)* void
        +add(Component)* void
        +remove(Component)* void
    }
    class Composite {
        -child List~Component~
        +print(level) void
        +add(Component) void
        +remove(Component) void
    }
    class Leaf {
        +print(level) void
        +add(Component) void
        +remove(Component) void
    }
    Component <|-- Composite
    Component <|-- Leaf
    Composite o-- Component : children

实现

public abstract class Component {
    protected String name;

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

    public void print() {
        print(0);
    }

    abstract void print(int level);

    abstract public void add(Component component);

    abstract public void remove(Component component);
}
public class Composite extends Component {
    private List<Component> child;

    public Composite(String name) {
        super(name);
        child = new ArrayList<>();
    }

    @Override
    void print(int level) {
        for (int i = 0; i < level; i++) {
            System.out.print("--");
        }
        System.out.println("Composite:" + name);
        for (Component component : child) {
            component.print(level + 1);
        }
    }

    @Override
    public void add(Component component) {
        child.add(component);
    }

    @Override
    public void remove(Component component) {
        child.remove(component);
    }
}

public class Leaf extends Component {
    public Leaf(String name) {
        super(name);
    }

    @Override
    void print(int level) {
        for (int i = 0; i < level; i++) {
            System.out.print("--");
        }
        System.out.println("left:" + name);
    }

    @Override
    public void add(Component component) {
        // 牺牲透明性换取单一职责原则,这样就不用做组件和叶子的类型判断
        throw new UnsupportedOperationException();
    }

    @Override
    public void remove(Component component) {
        throw new UnsupportedOperationException();
    }
}
public class Client {
    public static void main(String[] args) {
        Composite root = new Composite("root");
        Component node1 = new Leaf("1");
        Component node2 = new Composite("2");
        Component node3 = new Leaf("3");
        root.add(node1);
        root.add(node2);
        root.add(node3);

        Component node21 = new Leaf("21");
        Component node22 = new Composite("22");
        node2.add(node21);
        node2.add(node22);

        Component node221 = new Leaf("221");
        node22.add(node221);

        root.print();
    }
}

输出(一棵树形结构):

Composite:root
--left:1
--Composite:2
----left:21
----Composite:22
------left:221
--left:3

JDK 中的应用

  • javax.swing.JComponent#add(Component)
  • java.awt.Container#add(Component)
  • java.util.Map#putAll(Map)
  • java.util.List#addAll(Collection)
  • java.util.Set#addAll(Collection)
  • MyBatis 中 MixedSqlNode 组合各种动态 SQL 节点(IfSqlNodeTextSqlNode 等)

系列导航

← Angular 22+ 教程 11:属性型指令 Attribute Directives 目录 软件工程 011:面向过程管理:Scrum方式 →
← 返回文章列表