# Composite

# 概念

组合模式(Composite Pattern)是一种结构型设计模式,它将对象组合成树形结构来表示“部分-整体”的层次结构。组合模式使客户端可以以统一的方式对待单个对象和对象组合。

常用场景:

  • 文件系统(文件和文件夹)
  • 图形绘制(图形和组合图形)
  • 组织架构(员工和部门)

# 结构

  • Component(抽象组件): 定义了所有对象的公共接口,可以是叶子对象或容器对象。
  • Leaf(叶子节点): 叶子节点,没有子节点,实现具体操作。
  • Composite(容器节点): 容器节点,有子节点,实现组合操作。

# 例子

import java.util.ArrayList;
import java.util.List;

// 抽象组件
abstract class Employee {
    protected String name;
    protected double salary;

    public Employee(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }

    public abstract void showDetails();
}

// 叶子节点
class Developer extends Employee {
    public Developer(String name, double salary) {
        super(name, salary);
    }

    @Override
    public void showDetails() {
        System.out.println("Developer: " + name + ", Salary: " + salary);
    }
}

class Manager extends Employee {
    public Manager(String name, double salary) {
        super(name, salary);
    }

    @Override
    public void showDetails() {
        System.out.println("Manager: " + name + ", Salary: " + salary);
    }
}

// 容器节点
class Department extends Employee {
    private final List<Employee> employees = new ArrayList<>();

    public Department(String name) {
        super(name, 0); // 部门本身不关心工资
    }

    public void add(Employee e) {
        employees.add(e);
    }

    public void remove(Employee e) {
        employees.remove(e);
    }

    @Override
    public void showDetails() {
        System.out.println("Department: " + name);
        for (Employee e : employees) {
            e.showDetails();
        }
    }
}

// 测试类
public class CompositePatternDemo {
    public static void main(String[] args) {
        Developer dev1 = new Developer("Alice", 5000);
        Developer dev2 = new Developer("Bob", 6000);
        Manager man1 = new Manager("Charlie", 8000);

        Department devDept = new Department("Development");
        devDept.add(dev1);
        devDept.add(dev2);

        Department headDept = new Department("Head Office");
        headDept.add(man1);
        headDept.add(devDept);

        headDept.showDetails();
    }
}

在组合模式中:

  • 安全方式(Safe):叶子节点不提供 add/remove 方法,只能容器节点使用。
  • 透明方式(Transparent):在抽象组件(Component)中统一声明 add/remove 方法,叶子节点也会有这些方法(通常抛异常或不实现),客户端统一调用即可。
import java.util.ArrayList;
import java.util.List;

// 抽象组件
abstract class Graphic {
    protected String name;

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

    // 绘制方法
    public abstract void draw();

    // 透明方式统一声明 add/remove
    public void add(Graphic g) {
        throw new UnsupportedOperationException("不支持添加操作");
    }

    public void remove(Graphic g) {
        throw new UnsupportedOperationException("不支持删除操作");
    }
}

// 叶子节点
class Circle extends Graphic {
    public Circle(String name) {
        super(name);
    }

    @Override
    public void draw() {
        System.out.println("绘制圆形: " + name);
    }
}

class Rectangle extends Graphic {
    public Rectangle(String name) {
        super(name);
    }

    @Override
    public void draw() {
        System.out.println("绘制矩形: " + name);
    }
}

// 容器节点
class CompositeGraphic extends Graphic {
    private final List<Graphic> children = new ArrayList<>();

    public CompositeGraphic(String name) {
        super(name);
    }

    @Override
    public void draw() {
        System.out.println("组合图形: " + name + " 包含以下子图形:");
        for (Graphic g : children) {
            g.draw();
        }
    }

    @Override
    public void add(Graphic g) {
        children.add(g);
    }

    @Override
    public void remove(Graphic g) {
        children.remove(g);
    }
}

// 测试类
public class TransparentCompositeDemo {
    public static void main(String[] args) {
        // 创建叶子节点
        Graphic circle1 = new Circle("Circle 1");
        Graphic rect1 = new Rectangle("Rectangle 1");

        // 创建组合节点
        CompositeGraphic composite1 = new CompositeGraphic("Composite 1");
        composite1.add(circle1);
        composite1.add(rect1);

        // 创建更大的组合
        CompositeGraphic composite2 = new CompositeGraphic("Composite 2");
        composite2.add(new Circle("Circle 2"));
        composite2.add(composite1); // 可以直接添加组合节点

        // 绘制整个组合图形
        composite2.draw();
    }
}

# 优点

  • 统一了对单个对象和组合对象的操作。
  • 对树形结构的处理更加清晰。

# 缺点

  • 设计较复杂,增加了系统的抽象性。
  • 对于叶子节点和容器节点的区别可能增加理解成本。