# 聚合与聚合根（Aggregate & Aggregate Root）

URL: https://caijiao.org/ddd/chapter2/aggregate
Source: docs/ddd/chapter2/aggregate.md
Description: 深入理解聚合与聚合根的概念，掌握如何使用它们来构建领域模型中的业务边界和一致性规则。

在领域驱动设计（DDD）中，**聚合（Aggregate）** 和 **聚合根（Aggregate Root）** 是帮助我们划定业务边界、保证数据一致性的关键概念。通过正确设计聚合和聚合根，可以更好地组织系统的复杂业务逻辑。

## 聚合（Aggregate）

### 定义

聚合是由多个领域对象组成的集合，这些对象之间具有一定的关系，并且共同协作以保证一致性。聚合中的所有对象通过聚合根进行访问和操作，外部只能通过聚合根与聚合内部的实体进行交互。

### 特征

- **内部一致性**：聚合内部的对象协同工作，保持业务规则的一致性。
- **边界**：聚合定义了业务领域的边界，保证聚合内部的数据一致性。
- **聚合根**：聚合根是聚合的唯一入口，所有操作都必须通过聚合根来进行。

### 示例

假设在电商系统中，我们有一个**订单**聚合。订单聚合包含了订单条目、支付信息、发货信息等对象，但所有操作（如创建订单、修改订单条目）都应该通过**订单聚合根**进行。

## 聚合根（Aggregate Root）

### 定义

聚合根是聚合中的唯一入口点，它负责维护聚合内部的业务规则，并且保证聚合内部对象的一致性。聚合根通常是唯一标识该聚合的实体，外部系统只能通过聚合根来操作聚合中的对象。

### 特征

- **唯一入口点**：所有操作都必须通过聚合根进行，外部不能直接访问聚合内部的实体。
- **控制一致性**：聚合根确保聚合内部数据的一致性，负责处理所有的业务逻辑。
- **持久化与加载**：聚合根通常负责持久化和加载整个聚合，以保证数据的完整性。

### 示例

```java
public class Order {
    private final String orderId;
    private List<OrderItem> items;
    private Payment payment;
    private Shipping shipping;

    public Order(String orderId) {
        this.orderId = orderId;
        this.items = new ArrayList<>();
    }

    public String getOrderId() {
        return orderId;
    }

    public void addItem(OrderItem item) {
        items.add(item);
    }

    public void setPayment(Payment payment) {
        this.payment = payment;
    }

    public void setShipping(Shipping shipping) {
        this.shipping = shipping;
    }

    public void checkout() {
        // Ensure business rules and consistency are met
    }
}
```

在上面的示例中，`Order` 类是聚合根，负责管理订单中的所有对象（`OrderItem`、`Payment`、`Shipping`），并确保它们的一致性和业务规则。

## 聚合与聚合根的区别

| 特性     | 聚合（Aggregate）                  | 聚合根（Aggregate Root）           |
| -------- | ---------------------------------- | ---------------------------------- |
| 角色     | 包含多个领域对象，负责确保一致性   | 聚合的唯一入口点，负责协调内部对象 |
| 一致性   | 保证聚合内的对象数据一致性         | 保证聚合根的完整性与一致性         |
| 访问方式 | 只能通过聚合根来访问聚合内部的对象 | 聚合根是唯一可以被外部访问的对象   |
| 业务规则 | 聚合内的业务规则通过聚合根实现     | 聚合根负责聚合内所有业务规则的实现 |

## 聚合与聚合根的设计原则

1. **聚合的大小**：一个聚合不应过大，避免在业务操作中导致性能问题。聚合的大小应根据领域需求来划定。
2. **聚合根的职责**：聚合根不仅负责数据一致性，还需要处理与外部系统的交互，如持久化和事件发布。
3. **聚合之间的关系**：不同聚合之间应该保持低耦合，避免直接引用其他聚合的实体。如果需要跨聚合操作，可以通过领域服务或领域事件来完成。

## 实践建议

- 在设计领域模型时，如果有多个对象需要协作并保持一致性时，可以考虑将它们设计为一个聚合。
- 确保聚合的边界清晰，聚合内的所有操作必须通过聚合根进行，以确保数据一致性。
- 通过合理划分聚合和聚合根，避免系统的复杂度过高，并确保业务逻辑能够随着需求变化而演进。

通过合理使用聚合与聚合根，可以帮助开发人员设计出更加清晰和高效的领域模型，支持系统的长期可维护性。
