DDD相关概念
设计手段:战略设计,战术设计
领域建模:领域内实体,聚合根,值对象
领域服务
应用服务
充血模型:对象,服务
仓储,适配器
设计手段
战略设计是设计模块和边界,战术设计是详细设计实现。在官方推荐中,战略设计所有元素必不可少,战术设计可以根据项目复杂度自由裁剪。如果项目太简单可以不用过度设计。
战略设计
对复杂业务分治,微服务拆分服务,但拆太细会导致大量跨服务调用,反而退化为分布式单体。规定界限上下文,对于统一概念对象,在不同上下文中,可能有不同结构,需要详细区分。
战术设计
相较于扁平的 MVC 三层架构,贫血模型,使用 领域建模 和 充血模型。设计领域服务和应用服务。
界限上下文:
模型只在某个明确边界内成立,超出边界应重新定义。
领域建模
属于 DDD 的战术设计,包含对象建模和领域服务。
对象建模
对象建模,涉及概念有实体,聚合根,值对象。
实体:
由唯一标识,状态属性,动作构成。
值对象:
具有不可变性,可替换性。
聚合根:
把实体和值对象作为一个整体,外部仅通过整体访问,这个整体叫做聚合根,构建整体的过程叫做聚合。聚合的作用是维护事务一致性边界,边界内部要强一致性,边界外可以最终一致性。外部想要访问实体或值对象必须通过聚合根,统一外部访问入口。
领域服务
领域服务处于聚合的边界外,如没有特殊要求,一般采用最终一致性。这也是聚合划分的重要依据。同时不宜做得太长,原因是在应用层编排的时候,中间可能会想加钩子。
好的工程实践:
只做「一个完整、不可分割的领域行为」,通常 ≤ 3 个聚合,不超过一个业务语义节点。
应用服务
不属于领域建模,但是放在这里展开说明,方便区分。
在六边形架构中,领域对象和领域服务都放在 /domain ,应用服务放在 /application 。应用服务负责编排领域服务,领域事件,仓储。应用层还会做事务管理,安全控制,幂等性校验等工程细节。
领域事件就是领域服务里说的钩子,是通过事件发布订阅实现的。
充血模型体现
领域对象
使对象充血,把对象功能方法提取到内部。但是一般提供给聚合根再由外部访问。
举例:
比如说一个对象会有功能,拼接缓存键,对其缓存进行 CRUD。拼接缓存键的方法应该放在对象内部,然后提供给外部,不然不同服务需要做拼接缓存键的方法,那就会在内部重新实现。
领域服务
当逻辑不该放在某个实体上时,应该放在领域服务里。
这其实是充血模型思想的延伸:
- 不是一切都要塞进 Entity
- 无状态、跨聚合、有领域语义 → Domain Service
- 区别于 Application Service(编排 / 用例)
举例:
有一个场景是用户A给用户B转账。
正确做法:
- Account 只做“自己的钱怎么变”(充血),基础演示简化省略聚合,主要体现充血方法。
class Account {
private Money balance;
public void deposit(Money amount) {
balance = balance.add(amount);
}
}
- 转账逻辑 → Domain Service
class TransferService {
public void transfer(
Account from,
Account to,
Money amount) {
from.withdraw(amount);
to.deposit(amount);
}
}
- 应用层(Application Service)负责事务 & 编排
class TransferAppService {
@Transactional
public void transfer(String fromId, String toId, Money money) {
Account from = accountRepo.load(fromId);
Account to = accountRepo.load(toId);
transferService.transfer(from, to, money);
accountRepo.save(from);
accountRepo.save(to);
}
}
错误示例:
accountA.transferTo(accountB, money);
Account 现在要知道并操作另一个 Account,破坏聚合边界,事务责任不清(谁先谁后?失败回滚谁?)
一个聚合根不应直接修改另一个聚合根的内部状态
accountService.transfer(aId, bId, money);
直接访问里实体属性,这是贫血模型 + Service 编排,不是 DDD。
聚合根
对于实体和值对象的操作,应该有聚合根操作。
order.confirm(paymentInfo); // ✅ 行为在对象内
order.setStatus("CONFIRMED"); // ❌ 贫血
仓储,适配器
在领域层写仓储接口,基础设施层写适配器,符合依赖倒置原则。项目启动时,Spring框架会根据依赖自动注入。
1️⃣ 领域层只关心“能力”
public interface OrderRepository {
Order find(OrderId id);
void save(Order order);
}
2️⃣ Infrastructure 层“适配”它
@Repository
public class JpaOrderRepository implements OrderRepository {
private final SpringDataOrderJpaRepository jpa;
public Order find(OrderId id) {
return jpa.findById(id.value())
.map(OrderMapper::toDomain)
.orElseThrow(...);
}
}
拓展:
适配器不仅可以是数据库,缓存,还可以是 http,JSON,Token。
DDD 四色建模
目的
用面向对象的思想来设计,拆分现界上下文
四色建模过程
用户通过 决策命令,走 业务流程,完成 领域事件。领域事件触发 外部系统。
决策命令:触发条件
业务流程:一般指那些领域服务
领域事件:代表事情的完成,用过去时态描述
外部系统:由于事件的完成触发
一个业务流程可以触发多个领域事件。
举例:
场景:一个人受媳妇委托去超市买东西,自己想买包烟。
媳妇发出买东西的决策命令。行为人到超市,推了一辆购物车,这是业务流程,购物车为实体。行为人往购物车里装东西,这是业务流程。购物车被装满,这是领域事件。行为人买了一包烟,买烟是业务流程,烟被买完是领域事件。
战略设计
产品诉求
设定一个抽奖系统。用户通过签到获得积分。消耗积分抽奖获得奖品。随着抽奖次数增加,奖池会升级。运营可以通过后台配置抽奖策略,奖品库存。
用例图
说明用户和行为关系,比较简单,仅作为蓝图。有助于领域建模

领域建模
对于识别出来的用例,用四色模型进行建模。

进行领域划分,这一步是明确领域边界。

仅抽象领域边界,忽略四色建模元素。

DDD 架构设计
核心技术功能
功能开发常用涉及点
MVC架构图
使用MVC包管理下的技术点

DDD架构图
使用DDD包管理下的技术点
1.简洁分包

2.六边形架构

领域设计
少领域设计分包 VS 多领域设计分包

领域建模
