DDD代码结构
DDD代码结构
分层架构
DDD 推荐的分层架构将代码分为领域层、应用层、基础设施层和用户接口层。
项目结构:
order-service/
├── src/main/java/com/example/order/
│ ├── domain/ # 领域层(核心)
│ │ ├── model/
│ │ │ ├── Order.java # 聚合根
│ │ │ ├── OrderItem.java # 实体
│ │ │ ├── OrderId.java # 值对象
│ │ │ ├── Money.java # 值对象
│ │ │ └── OrderStatus.java # 枚举
│ │ ├── repository/
│ │ │ └── OrderRepository.java
│ │ ├── event/
│ │ │ └── OrderCreatedEvent.java
│ │ └── exception/
│ │ └── OrderNotFoundException.java
│ │
│ ├── application/ # 应用层
│ │ ├── service/
│ │ │ └── OrderApplicationService.java
│ │ ├── command/
│ │ │ ├── CreateOrderCommand.java
│ │ │ └── CancelOrderCommand.java
│ │ └── query/
│ │ └── OrderQueryService.java
│ │
│ ├── infrastructure/ # 基础设施层
│ │ ├── persistence/
│ │ │ ├── JpaOrderRepository.java
│ │ │ ├── OrderEntity.java
│ │ │ └── OrderMapper.java
│ │ ├── messaging/
│ │ │ └── OrderEventPublisher.java
│ │ └── config/
│ │ └── PersistenceConfig.java
│ │
│ └── interfaces/ # 用户接口层
│ ├── rest/
│ │ └── OrderController.java
│ └── dto/
│ ├── CreateOrderRequest.java
│ └── OrderResponse.java
聚合根实现
// 聚合根:订单
@Entity
@Table(name = "orders")
public class Order {
@Id
private Long id;
@Column(name = "order_no")
private String orderNo;
@Column(name = "customer_id")
private Long customerId;
@Enumerated(EnumType.STRING)
private OrderStatus status;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "order_id")
private List<OrderItem> items = new ArrayList<>();
@Version
private Long version; // 乐观锁
private List<DomainEvent> domainEvents = new ArrayList<>();
// 工厂方法
public static Order create(Long customerId, List<OrderItem> items) {
Order order = new Order();
order.id = generateId();
order.orderNo = generateOrderNo();
order.customerId = customerId;
order.status = OrderStatus.CREATED;
order.items = new ArrayList<>(items);
// 产生领域事件
order.registerEvent(new OrderCreatedEvent(order.id, order.orderNo));
return order;
}
// 业务方法
public void pay(Money amount) {
if (this.status != OrderStatus.CREATED) {
throw new InvalidOrderStateException("只有待支付订单可以支付");
}
this.status = OrderStatus.PAID;
registerEvent(new OrderPaidEvent(this.id, amount));
}
public void cancel() {
if (this.status == OrderStatus.SHIPPED) {
throw new InvalidOrderStateException("已发货订单不能取消");
}
this.status = OrderStatus.CANCELLED;
registerEvent(new OrderCancelledEvent(this.id));
}
// 领域事件管理
private void registerEvent(DomainEvent event) {
domainEvents.add(event);
}
public List<DomainEvent> getDomainEvents() {
return Collections.unmodifiableList(domainEvents);
}
public void clearEvents() {
domainEvents.clear();
}
}
Repository 实现
// Repository 接口(领域层)
public interface OrderRepository {
Optional<Order> findById(Long id);
Optional<Order> findByOrderNo(String orderNo);
List<Order> findByCustomerId(Long customerId);
Order save(Order order);
void deleteById(Long id);
}
// JPA 实现(基础设施层)
@Repository
public class JpaOrderRepository implements OrderRepository {
private final OrderJpaRepository jpaRepository;
private final OrderMapper mapper;
@Override
public Optional<Order> findById(Long id) {
return jpaRepository.findById(id).map(mapper::toDomain);
}
@Override
public Order save(Order order) {
OrderEntity entity = mapper.toEntity(order);
OrderEntity saved = jpaRepository.save(entity);
return mapper.toDomain(saved);
}
}
// Mapper 转换
@Component
public class OrderMapper {
public Order toDomain(OrderEntity entity) {
Order order = new Order();
order.setId(entity.getId());
order.setOrderNo(entity.getOrderNo());
order.setCustomerId(entity.getCustomerId());
order.setStatus(entity.getStatus());
order.setItems(entity.getItems().stream()
.map(this::toDomainItem)
.collect(Collectors.toList()));
return order;
}
public OrderEntity toEntity(Order order) {
OrderEntity entity = new OrderEntity();
entity.setId(order.getId());
entity.setOrderNo(order.getOrderNo());
entity.setCustomerId(order.getCustomerId());
entity.setStatus(order.getStatus());
entity.setItems(order.getItems().stream()
.map(this::toEntityItem)
.collect(Collectors.toList()));
return entity;
}
}
DDD 代码结构的核心是让领域层保持纯净,不依赖任何基础设施。