第二十二课:领域建模实战——订单系统最小闭环(实战篇)

在上一篇《领域建模入门》中,我们讲了:

  • Entity
  • Value Object
  • Aggregate
  • Domain Service
  • Bounded Context
  • 统一语言
  • 状态机
  • 规则归属

但如果只停留在概念层面,领域建模很容易变成"看懂却不会用"。

这一篇,我们用一个 最小订单系统闭环

把领域建模从"概念"落到"结构"。

一、实战目标

我们只实现三个功能:

  1. 创建订单
  2. 支付订单
  3. 取消订单

不引入:

  • MQ
  • Redis
  • 微服务
  • 分布式锁

目标只有一个:

看清规则归属,而不是炫技术。

二、业务规则梳理

先从业务说起,而不是从代码说起。

订单规则

  • 创建时必须有金额
  • 未支付可以取消
  • 已支付不能取消
  • 支付后状态变更

你会发现:

这些规则都属于"订单本身"。

这就是 Domain。

三、模块结构设计

复制代码
order
 ├─ domain
 ├─ biz
 ├─ repository
 ├─ api
 └─ dto

四、Domain 层建模

1. Value Object:Money

java 复制代码
public class Money {
    private final BigDecimal amount;

    public Money(BigDecimal amount) {
        if (amount.compareTo(BigDecimal.ZERO) < 0) {
            throw new IllegalArgumentException("金额不能为负");
        }
        this.amount = amount;
    }

    public BigDecimal getAmount() {
        return amount;
    }
}

特点:

  • 不可变
  • 无 ID
  • 只代表值

2. Entity:Order

java 复制代码
public class Order {

    private Long id;
    private Money money;
    private OrderStatus status;

    public Order(Money money) {
        this.money = money;
        this.status = OrderStatus.CREATED;
    }

    public void pay() {
        if (status != OrderStatus.CREATED) {
            throw new RuntimeException("当前状态不可支付");
        }
        status = OrderStatus.PAID;
    }

    public void cancel() {
        if (status == OrderStatus.PAID) {
            throw new RuntimeException("已支付订单不能取消");
        }
        status = OrderStatus.CANCELLED;
    }
}

体现点:

  • 状态机
  • 规则归属
  • 行为内聚

3. 状态枚举

java 复制代码
public enum OrderStatus {
    CREATED,
    PAID,
    CANCELLED
}

五、Repository(持久化接口)

java 复制代码
public interface OrderRepository {
    void save(Order order);
    Order findById(Long id);
}

关键点:

Domain 不直接写 SQL。

六、Biz 层(流程编排)

java 复制代码
public class OrderBizService {

    private OrderRepository repository;

    public void createOrder(BigDecimal amount) {
        Order order = new Order(new Money(amount));
        repository.save(order);
    }

    public void payOrder(Long id) {
        Order order = repository.findById(id);
        order.pay();
        repository.save(order);
    }

    public void cancelOrder(Long id) {
        Order order = repository.findById(id);
        order.cancel();
        repository.save(order);
    }
}

Biz 做的事:

  • 串联流程
  • 调用 Domain
  • 持久化

Biz 不做的事:

  • 不判断规则
  • 不计算金额

七、Controller 层(简化示意)

java 复制代码
@RestController
public class OrderController {

    private OrderBizService service;

    @PostMapping("/create")
    public void create(BigDecimal amount) {
        service.createOrder(amount);
    }
}

Controller 只负责:

输入输出,不负责业务。

八、这个实战体现了哪些建模点?

知识点 体现位置
Entity Order
Value Object Money
Aggregate Order
状态机 OrderStatus
规则归属 pay / cancel
Repository OrderRepository
Biz 编排 OrderBizService

九、为什么不加 MQ / Redis?

因为这篇的目标不是"系统复杂度",

而是:

规则清晰度。

一旦加太多技术,读者会迷失。

十、实战结论

你会发现:

Controller 没有业务逻辑

Biz 没有规则判断

Domain 没有 SQL

Repository 没有业务规则

这就是领域建模的落地效果。

十一、实战口诀

可以记这四句:

规则进 Domain

流程进 Biz

数据进 Repository

输入输出给 Controller

做到这四点,

你的系统就从"堆代码"进化为"有结构"。

相关推荐
长栎1 分钟前
命令模式和策略模式代码长一样——你分不清是因为你没看穿它们的本质
后端
用户298698530142 分钟前
Java Word 文档样式进阶:段落与文本背景色设置完全指南
java·后端
苍何3 分钟前
开源个狠活,世界杯 AI 模型竞技场!
后端
Dilee4 分钟前
Spring AI 1.1.7 接入 MCP:Filesystem Server 最小 Demo
人工智能·后端
程序员小富6 分钟前
我开源了一个开发者专属的智能 JSON 工具,得到了媳妇高度认可
前端·vue.js·后端
苍何10 分钟前
深度测评 MiniMax M3,能打但不贵
后端
苍何10 分钟前
爆款博主,已经没有秘密了。。。
后端
dunky16 分钟前
Spring 的三级缓存与循环依赖
后端·spring
子兮曰19 分钟前
AI Coding Method Map:一张图看懂 AI 编程的完整链路
前端·人工智能·后端