学习笔记八
领域驱动设计核心概念
为什么需要DDD?
java
// 传统CRUD开发的痛点
@Service
public class OrderService {
// 贫血模型:只有数据,没有业务逻辑
@Data
public class Order {
private Long id;
private Long userId;
private BigDecimal amount;
private String status;
private List<OrderItem> items;
// 只有getter/setter,没有业务方法
}
// 业务逻辑散落在Service中
public void submitOrder(Order order) {
// 1. 校验库存
checkInventory(order);
// 2. 计算金额
calculateAmount(order);
// 3. 检查用户余额
checkUserBalance(order);
// 4. 扣减库存
reduceInventory(order);
// 5. 创建订单
saveOrder(order);
// 6. 发送消息
sendOrderCreatedEvent(order);
}
}
/*
问题:
-
业务逻辑无法复用
-
领域知识丢失
-
需求变更困难
-
代码难以理解
*/
DDD核心概念
java
// 1. 实体(Entity):有唯一标识,可变
@Getter
public class Order {
private final OrderId id; // 值对象作为ID
private OrderStatus status; // 状态枚举
private Money totalAmount; // 值对象
private Listitems;
private DeliveryAddress deliveryAddress;// 实体有业务行为
public void addItem(Product product, int quantity) {
// 业务规则:不能添加已取消订单的商品
if (this.status == OrderStatus.CANCELLED) {
throw new OrderAlreadyCancelledException();
}OrderItem item = new OrderItem(product, quantity); this.items.add(item); this.totalAmount = calculateTotalAmount(); // 重新计算总额}
public void submit() {
// 业务规则:订单必须有商品
if (items.isEmpty()) {
throw new EmptyOrderException();
}// 业务规则:金额必须大于0 if (totalAmount.lessThan(Money.ZERO)) { throw new InvalidOrderAmountException(); } this.status = OrderStatus.SUBMITTED; registerEvent(new OrderSubmittedEvent(this.id));}
public void cancel() {
// 业务规则:已支付的订单不能取消
if (this.status == OrderStatus.PAID) {
throw new PaidOrderCannotBeCancelledException();
}this.status = OrderStatus.CANCELLED; registerEvent(new OrderCancelledEvent(this.id));}
}
// 2. 值对象(Value Object):无标识,不可变
@Value
public class Money {
BigDecimal amount;
Currency currency;
// 业务方法:加法(返回新对象,不修改原对象)
public Money add(Money other) {
if (!this.currency.equals(other.currency)) {
throw new CurrencyMismatchException();
}
return new Money(this.amount.add(other.amount), this.currency);
}
// 业务规则验证
public boolean isGreaterThan(Money other) {
return this.amount.compareTo(other.amount) > 0;
}
}
// 3. 聚合(Aggregate):一致性边界
public class Order extends AggregateRoot
private List<OrderItem> items; // 聚合内的实体
private Payment payment; // 聚合内的值对象
private DeliveryInfo deliveryInfo; // 聚合内的值对象
// 聚合内的一致性规则
public void pay(CreditCard card) {
// 规则1:只能支付已提交的订单
if (this.status != OrderStatus.SUBMITTED) {
throw new InvalidOrderStatusException();
}
// 规则2:支付金额必须等于订单总额
Payment payment = new Payment(this.totalAmount, card);
this.payment = payment;
this.status = OrderStatus.PAID;
registerEvent(new OrderPaidEvent(this.id));
}
// 通过ID引用其他聚合
private UserId userId; // 只引用ID,不直接引用User聚合
}
// 4. 领域服务(Domain Service):跨多个聚合的业务逻辑
@Service
@DomainService
public class OrderPlacementService {
private final OrderRepository orderRepository;
private final InventoryService inventoryService;
private final PaymentService paymentService;
public Order placeOrder(Order order, PaymentInfo payment) {
// 跨聚合的业务逻辑
// 1. 检查库存
inventoryService.checkAvailability(order.getItems());
// 2. 创建订单(Order聚合的行为)
order.submit();
// 3. 处理支付(Payment聚合的行为)
payment.process(order.getTotalAmount());
// 4. 保存订单
orderRepository.save(order);
return order;
}
}
// 5. 领域事件(Domain Event):记录重要事件
@Getter
public class OrderSubmittedEvent extends DomainEvent {
private final OrderId orderId;
private final Money totalAmount;
private final LocalDateTime submittedAt;
public OrderSubmittedEvent(OrderId orderId, Money totalAmount) {
this.orderId = orderId;
this.totalAmount = totalAmount;
this.submittedAt = LocalDateTime.now();
}
}
// 事件监听器
@Component
public class OrderEventListener {
@EventListener
public void handleOrderSubmitted(OrderSubmittedEvent event) {
// 1. 发送通知
sendNotification(event);
// 2. 更新统计
updateStatistics(event);
// 3. 触发后续流程
startWorkflow(event);
}
}

浙公网安备 33010602011771号