领域驱动设计-聚合根与实体定义和区别

在领域驱动设计(DDD)中,聚合根(Aggregate Root)和实体(Entity)都是领域模型中的重要概念,它们在模型中扮演不同的角色,具有不同的特点。

实体(Entity)

实体是具有唯一标识符的对象,它们可以拥有生命周期,并在系统中存在一段时间。实体可以是聚合的一部分,也可以独立存在。实体的属性可以随着时间改变,并且它们的身份是持久的。

特点:

  • 唯一性:每个实体都有一个唯一标识符。
  • 生命周期:实体可以被创建、修改和删除。
  • 持久性:实体的身份和状态在系统中是持久的。

聚合根(Aggregate Root)

聚合根是一组相关对象的集合,这些对象共同形成一个“聚合”。聚合根是聚合的入口点,它定义了聚合的边界,并且控制对聚合内部对象的访问。聚合根本身也是一个实体,但它还承担了额外的责任,如维护聚合的一致性和完整性。

特点:

  • 一致性:聚合根负责确保在聚合内部的所有对象状态的一致性。
  • 边界:聚合根定义了聚合的边界,外部对象只能通过聚合根与聚合内部的对象交互。
  • 入口点:聚合根是外部世界与聚合内部对象交互的唯一入口。
  • 实体:聚合根本身是一个实体,但它还承担了聚合的责任。

区别

  1. 角色:实体是领域模型中的普通对象,而聚合根是具有特定责任的实体,如维护一致性和定义边界。
  2. 一致性:聚合根负责维护聚合内对象的一致性,而实体本身不承担这一责任。
  3. 访问控制:聚合根控制对聚合内部对象的访问,外部对象不能直接访问聚合内部的对象。
  4. 边界:聚合根定义了聚合的边界,而实体没有这一概念。
  5. 生命周期:虽然聚合根本身是一个实体,具有生命周期,但它的生命周期管理通常与聚合内其他对象的生命周期紧密相关。

示例

假设我们有一个电子商务系统,其中包含订单(Order)和订单项(OrderItem)。

  • 订单(Order):可以作为聚合根,因为它定义了订单的边界,控制对订单项的访问,并维护订单的一致性。
  • 订单项(OrderItem):是聚合的一部分,但它本身不是聚合根,它依赖于订单聚合根来维护其生命周期和一致性。

在代码实现中,聚合根可能会包含对内部对象的引用,并提供方法来管理这些对象,同时确保整个聚合的一致性。

public class Order : AggregateRoot
{
    private List<OrderItem> orderItems = new List<OrderItem>();

    public void AddOrderItem(Product product, int quantity, decimal price)
    {
        var orderItem = new OrderItem(product, quantity, price);
        orderItems.Add(orderItem);
        // 这里可以添加额外的逻辑来维护订单的一致性
    }

    // 其他方法...
}

public class OrderItem
{
    public Product Product { get; private set; }
    public int Quantity { get; private set; }
    public decimal Price { get; private set; }

    public OrderItem(Product product, int quantity, decimal price)
    {
        Product = product;
        Quantity = quantity;
        Price = price;
    }

    // OrderItem 不是聚合根,因此没有管理聚合的责任
}

在这个示例中,Order 类是聚合根,它管理 OrderItem 对象的集合,并提供添加订单项的方法。OrderItem 类是一个实体,但它不是聚合根,它依赖于 Order 聚合根来维护其生命周期和一致性。

Leave a Comment

您的邮箱地址不会被公开。 必填项已用 * 标注