聚合根是聚合的唯一入口和业务规则守门人,负责维护不变量、确保事务原子性,并禁止外部直接访问内部对象;它是一个有唯一标识的实体,统领聚合内其他实体与值对象。

聚合根是领域驱动设计(DDD)中组织业务逻辑和保障数据一致性的关键角色,不是技术容器,而是业务规则的守门人。
聚合根是聚合的唯一入口
一个聚合是一组业务上强关联的对象(比如订单、订单项、订单状态),它们必须作为一个整体被创建、修改或删除。聚合根就是这个整体对外暴露的唯一实体。外部代码不能直接操作订单项,只能通过订单对象调用 AddOrderItem() 或 ChangeStatus() 等方法。这种限制防止了绕过业务规则的非法修改,比如跳过校验直接更新订单项数量导致总金额错乱。
- 外部对象只能持有聚合根的 ID,不能持有内部实体的引用
- 仓储(Repository)只负责加载和保存聚合根,不提供对内部对象的单独查询接口
- 跨聚合访问必须通过 ID 关联,再由目标聚合根提供所需能力
聚合根负责维护内部一致性
它不只是“转发请求”的中介,而是主动执行业务约束的协调者。例如在审批流程中,“只有所有步骤都通过,整个流程才算批准”是一条不变式(invariant)。聚合根 ApprovalProcess 必须封装这条规则:当某个步骤被标记为通过时,它要检查全部步骤状态,并自动更新自身状态;若有人试图绕过它直接改写某一步骤的状态,系统应拒绝——因为那不在它的管辖边界内。
- 所有影响聚合状态的变更,必须经由聚合根的方法触发
- 聚合根内部可调用私有方法或委托给领域服务,但入口始终唯一
- 数据库事务通常以聚合为单位提交,确保原子性
聚合根必须能独立存在
它代表一个有明确业务意义的最小完整单元。比如文档类型(DocumentType)和具体文档(Document)不是同一聚合:前者定义结构,后者承载实例数据。Document 可以独立存在并拥有生命周期(创建、提交、归档),而 DocumentType 是配置型对象,通常由管理后台维护。所以 Document 更适合作为聚合根,其属性值(AttributeValue)、审批流程(ApprovalProcess)等都应作为它所管理的子对象或关联聚合来设计。
- 聚合内其他实体/值对象不能脱离聚合根单独存活
- 聚合根应具备完整业务身份(如唯一ID、明确生命周期)
- 避免把“只是被频繁一起读取”的对象硬塞进同一聚合,会导致边界模糊和性能问题
聚合根与值对象、实体的关系
聚合根本身是一个实体(有唯一标识和可变状态),但它统领着聚合内的其他实体和值对象。值对象(如地址、金额、时间范围)没有身份,只描述特征;而子实体(如订单项、审批步骤)虽有ID,但仅在聚合上下文中才有意义。聚合根决定它们如何被创建、组合、验证和销毁。
- 值对象应不可变,通过聚合根构造或工厂方法生成
- 子实体的ID通常由聚合根生成或管理,不对外暴露构造函数
- 聚合根可通过工厂方法(如 Order.Create())控制合法实例的诞生










