本文以电商领域为例,介绍如何通过状态机模型来完善领域模型缺失的业务方法,同时在实现上保持领域模型的业务一致性。
初始建模
为电子商城建模,得到领域模型Order、OrderStatus、OrderItem、Product,每个模型都具备相应的业务属性:

领域对象的生命周期会经历不同的阶段,我们常常会使用UML状态图来对领域模型生命周期进行建模:

可以看到,订单Order初始由用户初始创建后,状态为待付款
,用户支付订单后,Order状态变更为待发货
,商家发货后,Order状态变更为待签收
,用户确认收货后,Order状态变更为已完成
。
完善模型
识别状态模型上的Action并将其转化为领域模型方法:
- 创建订单: Order(items)构造器,状态变更为
待付款Paying
,更新statusTimestamp为当前时间 - 支付:pay(),状态变更为
待发货Shipping
,更新statusTimestamp为当前时间 - 发货:ship(),状态变更为
待收货Deliverying
,更新statusTimestamp为当前时间 - 收货:delivery(),状态变更为
已完成Completed
,更新statusTimestamp为当前时间

实现模型
在设计阶段,我们得到了领域模型上应该有哪些业务方法,现在我们只需要将方法填充到Order对象,并在方法内部实现即可:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
| @Getter
public class Order {
private String number;
private OrderStatus status;
private Long statusTimestamp;
private List<OrderItem> items;
// 创建订单
public Order(List<OrderItem> items) {
this.number = UUID.randomUUID().toString();
this.items = items;
this.status = OrderStatus.Paying; // 这里初始化领域对象的状态为待付款
this.statusTimestamp = System.currentTimeMillis();
}
// 支付
public void pay() {
if (this.status != OrderStatus.Paying) {
throw new IllegalStateException();
}
this.status = OrderStatus.Shipping;
this.statusTimestamp = System.currentTimeMillis();
}
// 发货
public void ship() {
if (this.status != OrderStatus.Shipping) {
throw new IllegalStateException();
}
this.status = OrderStatus.Deliverying;
this.statusTimestamp = System.currentTimeMillis();
}
// 收货
public void delivery() {
if (this.status != OrderStatus.Deliverying) {
throw new IllegalStateException();
}
this.status = OrderStatus.Completed;
this.statusTimestamp = System.currentTimeMillis();
}
}
public enum OrderStatus {
Paying,
Shipping,
Delivering,
Completed
}
@Getter
@RequiredArgsConstructor
public class OrderItem {
private final Product product;
private final int quantity;
}
@Getter
@RequiredArgsConstructor
public class Product {
private final String code;
private final String name;
}
|
可以看到,Order模型的类、属性、方法定义均和建模设计阶段保持了一致性。
接下来是什么?
在编码实现以后,我们将会进行测试。下一篇将介绍如何为领域模型编写单元测试。