2. 领域驱动设计基础回顾:实体、值对象、领域服务、领域事件的核心定义

在深入聚合根与微服务边界之前,必须重新校准 DDD 战术模式的四个基本构造块。它们不仅是建模语言,更是微服务拆分时判断“该不该独立成一个服务”的底层依据。

2.1 实体(Entity)—— 拥有身份标识与连续生命周期的对象

实体是 DDD 中最核心的概念。一个实体具备唯一标识,并且这个标识在其整个生命周期中保持不变。判断一个对象是否为实体,不取决于它的属性值,而取决于它是否拥有一个不可变的 ID。

特征 说明 典型示例
唯一标识 通过 ID(UUID、自增主键、业务编号)区分不同实例 用户ID、订单ID、聚合根ID
可变性 属性可以修改,但身份不变 用户修改昵称,仍是同一个用户
生命周期 从创建到持久化再到归档,身份持续存在 订单从待支付到已完成
相等性 通过 ID 比较,而非属性值 两个同名用户,ID不同则不同实体
建模提示: 在微服务拆分时,实体通常对应数据库中的主表,且其 ID 是跨服务通信时唯一可用的引用句柄。如果一个对象没有独立生命周期,不要强行建模为实体。

2.2 值对象(Value Object)—— 描述性、不可变、无身份

值对象描述领域的某个度量或描述,它没有概念上的身份标识,其相等性完全基于所有属性的值。值对象一旦创建就不可变,修改即替换。

  • 无身份: 两个“金额 100 元、币种人民币”的值对象,就是同一个值对象。
  • 不可变: 修改地址不是修改原对象,而是创建新地址对象替换引用。
  • 自包含: 值对象内部可以包含其他值对象或实体引用,但整体无独立生命周期。
  • 可共享: 同一个值对象实例可以被多个实体安全共享。
对比维度 实体 值对象
身份标识 有(ID) 无
可变性 可变 不可变
相等性 ID 相等 所有属性相等
生命周期 独立 依附于实体
数据库存储 独立表 内嵌或序列化
微服务映射: 值对象通常作为实体的属性内嵌存储,不单独建表。在服务间传输时,值对象以不可变 DTO 形式传递,天然适合事件溯源中的快照。
实体 vs 值对象 核心差异 实体(Entity) • 拥有唯一标识(ID) • 属性可变,身份不变 • 独立生命周期 • 通过 ID 比较相等性 • 示例:用户、订单、账户 数据库:独立主表,ID 为主键 值对象(Value Object) • 无身份标识 • 创建后不可变 • 依附于实体存在 • 所有属性值决定相等性 • 示例:地址、金额、时间段 数据库:内嵌字段或 JSON 列

2.3 领域服务(Domain Service)—— 无状态、跨实体的业务逻辑

当某个业务操作不属于某个实体或值对象的自然职责时,就需要领域服务。领域服务是无状态的,它协调多个领域对象完成一个业务动作。

  • 无状态: 不持有自己的数据,只依赖传入的领域对象。
  • 行为聚焦: 封装一个完整的业务原子操作。
  • 命名规范: 通常以动词或动词短语命名,如 TransferService、FraudDetectionService。
  • 与基础设施服务区分: 领域服务只包含业务规则,不涉及数据库、消息队列等基础设施。
常见误区: 不要把所有操作都塞进领域服务。如果一个操作可以自然地放在实体方法中(如 order.calculateTotal()),就不要提取到服务中。领域服务是“最后的手段”,不是“默认选择”。
// 领域服务示例:转账
public class TransferService {
    public void transfer(Account from, Account to, Money amount) {
        // 领域规则:扣款
        from.debit(amount);
        // 领域规则:入账
        to.credit(amount);
        // 领域事件:转账完成
        DomainEventPublisher.publish(new TransferCompleted(from.getId(), to.getId(), amount));
    }
}

2.4 领域事件(Domain Event)—— 记录已发生的业务事实

领域事件表示领域中已经发生的、对业务有意义的事件。它是 DDD 中实现最终一致性和事件驱动架构的核心机制。

属性 说明 示例值
事件名称 过去时态的动词短语 OrderPlaced
事件 ID 全局唯一标识 UUID
发生时间 事件产生的时间戳 2025-01-15T10:30:00Z
事件数据 与事件相关的业务数据 订单ID、金额、用户ID
版本号 事件 schema 版本 1.0
微服务价值: 领域事件是微服务之间异步解耦的基石。一个服务发布事件,其他服务订阅并做出反应,无需同步调用。例如:订单服务发布 OrderPaid 事件,库存服务订阅后扣减库存,物流服务订阅后创建发货单。
领域事件驱动流程 订单服务 (事件发布者) 事件总线 (消息中间件) 库存服务 物流服务 通知服务 OrderPlaced 事件

2.5 四种构造块的关系总结

在领域模型中,这四种构造块协同工作:实体作为身份锚点,值对象作为属性描述,领域服务协调跨实体的业务逻辑,领域事件记录业务事实并驱动后续流程。理解它们的边界,是后续定义聚合根和微服务拆分的前提。

记忆口诀: “实体有身份,值对象无身份;服务管行为,事件记事实。” 在建模时,先识别实体,再填充值对象,遇到跨实体逻辑提取领域服务,最后用领域事件解耦。