学习笔记八

领域驱动设计核心概念
为什么需要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);
}

}

/*
问题:

  1. 业务逻辑无法复用

  2. 领域知识丢失

  3. 需求变更困难

  4. 代码难以理解
    */
    DDD核心概念
    java
    // 1. 实体(Entity):有唯一标识,可变
    @Getter
    public class Order {
    private final OrderId id; // 值对象作为ID
    private OrderStatus status; // 状态枚举
    private Money totalAmount; // 值对象
    private List items;
    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);
}

}

posted @ 2026-03-12 22:07  Lomook  阅读(4)  评论(0)    收藏  举报