# DDD 实现
作者:Ethan.Yang
博客:https://blog.ethanyang.cn (opens new window)
# DDD架构:单体应用实现
在单体应用中,虽然所有的业务逻辑、数据和服务都运行在同一个进程和数据库中,但依然可以遵循 DDD 的设计原则,利用 领域模型 来组织代码,并通过 模块化 来划分业务领域。
# 核心领域模型
在单体应用中,DDD 的核心概念(如实体、值对象、聚合根、领域服务等)依然适用。你可以将系统的不同业务领域抽象为独立的 领域模型,并确保每个模块专注于自己的业务功能。
举个例子,假设我们在构建一个电商系统,其中涉及订单、支付、库存和物流等多个业务领域。
// 订单领域模型(Order Domain)
public class Order {
private String id;
private String customerId;
private List<OrderItem> items;
private OrderStatus status;
public void addItem(OrderItem item) {
// 业务逻辑:添加商品到订单
}
public void changeStatus(OrderStatus newStatus) {
// 业务逻辑:修改订单状态
this.status = newStatus;
}
// 其他领域方法
}
public class OrderItem {
private String productId;
private int quantity;
// 其他领域方法
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 模块化设计
在单体应用中,你可以通过 模块 来划分领域。每个模块对应系统中的一个领域,模块内部可以有实体、聚合根、值对象、领域服务等,而模块之间通过接口和领域事件进行交互。
- 订单模块(Order Module):包含订单相关的所有实体、聚合根和领域服务。
- 支付模块(Payment Module):处理支付相关的业务逻辑。
- 库存模块(Inventory Module):管理商品库存。
- 物流模块(Logistics Module):处理物流配送。
模块划分有助于代码的清晰性和可维护性。在 Spring 框架中,模块可以通过包结构、接口层、服务层等方式实现。
// 订单服务(Order Service)
@Service
public class OrderService {
private final OrderRepository orderRepository;
public OrderService(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
public void createOrder(Order order) {
orderRepository.save(order); // 订单保存到数据库
}
public void updateOrderStatus(String orderId, OrderStatus status) {
Order order = orderRepository.findById(orderId);
order.changeStatus(status);
orderRepository.save(order);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 领域事件与防腐层
即使在单体应用中,领域事件和防腐层的概念也非常重要。如果不同模块之间需要通过事件进行通信,或者某个模块需要调用外部系统,我们依然可以使用领域事件和防腐层。
例如,库存模块可能需要在订单成功支付后减少库存,这时可以通过领域事件来解耦订单服务与库存服务。
// 订单支付成功后发布领域事件
public class OrderPaidEvent {
private String orderId;
private String customerId;
// 构造函数、getter、setter等
}
@Service
public class OrderService {
private final ApplicationEventPublisher eventPublisher;
public OrderService(ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
public void payOrder(String orderId) {
// 支付成功,发布领域事件
eventPublisher.publishEvent(new OrderPaidEvent(orderId, "customer123"));
}
}
// 库存服务监听订单支付成功事件
@Service
public class InventoryService {
@EventListener
public void handleOrderPaidEvent(OrderPaidEvent event) {
// 处理库存减少的业务逻辑
}
}
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
# 单体应用中的防腐层
如果你的单体应用需要与外部系统集成,防腐层依然可以用来隔离外部服务的实现细节,确保你内部的领域模型不受外部服务影响。
public class ExternalPaymentService {
public PaymentResponse makePayment(PaymentRequest request) {
// 调用外部支付服务
return new PaymentResponse();
}
}
public class PaymentFacade {
private final ExternalPaymentService externalPaymentService;
public PaymentFacade(ExternalPaymentService externalPaymentService) {
this.externalPaymentService = externalPaymentService;
}
public PaymentResponse processPayment(PaymentRequest request) {
// 防腐层:转换请求数据并调用外部支付服务
return externalPaymentService.makePayment(request);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# DDD架构:微服务实现
在微服务架构中,DDD 的设计理念依然适用,只不过由于微服务本身是 分布式 的,我们需要更加关注服务间的通信、数据一致性和领域解耦等问题。
# 微服务中的领域(服务)
在微服务架构中,每个 领域 对应一个独立的 微服务。每个微服务聚焦于自己的业务领域,拥有自己的数据存储、API 和业务逻辑。微服务之间通常通过 REST、GraphQL、gRPC 或消息队列等方式进行通信。
例如,订单、支付、库存等每个模块都可以是一个独立的微服务:
- 订单微服务(Order Service):处理与订单相关的所有操作。
- 支付微服务(Payment Service):专注于支付逻辑。
- 库存微服务(Inventory Service):负责库存管理。
每个微服务都根据 DDD 的设计原则,围绕各自的领域来构建。
# 微服务间的通信与防腐层
在微服务架构中,防腐层尤为重要。因为服务间的通信往往会涉及到数据的转换、协议的适配以及接口的规范等,防腐层可以帮助微服务之间保持独立性。
// 库存微服务通过 REST API 与订单微服务通信
public class InventoryService {
private final RestTemplate restTemplate;
public InventoryService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
public InventoryResponse checkInventory(String productId) {
// 防腐层:调用外部订单微服务
return restTemplate.getForObject("http://order-service/checkInventory/" + productId, InventoryResponse.class);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
# 跨微服务的领域事件
在微服务架构中,领域事件 是解耦微服务之间的重要手段。当一个微服务的领域模型发生变化时,它会发布领域事件,其他微服务可以订阅这些事件并做出响应。通过这种方式,微服务之间可以在不直接依赖的情况下协同工作。
举个例子,订单微服务 在订单支付成功后发布 OrderPaidEvent,库存微服务 订阅这个事件并更新库存。
// 订单微服务发布领域事件
public class OrderPaidEvent {
private String orderId;
// 构造函数、getter、setter等
}
// 库存微服务订阅领域事件
public class InventoryService {
@EventListener
public void handleOrderPaidEvent(OrderPaidEvent event) {
// 更新库存
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# 业务聚合层(BP层)
在微服务架构中,业务聚合层(BP层)常常作为 API 网关 或 业务协调层,它负责从多个微服务中获取数据并进行聚合,然后返回给前端。BP层避免了前端直接调用多个微服务的多个 API,提升了性能和用户体验。
public class OrderBPService {
private final OrderService orderService;
private final PaymentService paymentService;
private final InventoryService inventoryService;
public OrderBPService(OrderService orderService, PaymentService paymentService, InventoryService inventoryService) {
this.orderService = orderService;
this.paymentService = paymentService;
this.inventoryService = inventoryService;
}
public OrderDetailsDTO getOrderDetails(String orderId) {
// 调用多个微服务并聚合数据
Order order = orderService.getOrder(orderId);
PaymentStatus paymentStatus = paymentService.getPaymentStatus(orderId);
InventoryStatus inventoryStatus = inventoryService.getInventoryStatus(order.getProductId());
return new OrderDetailsDTO(order, paymentStatus, inventoryStatus);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 微服务中的防腐层
在微服务架构中,防腐层通常表现为 服务间的适配层,它可以负责处理不同微服务之间的通信协议、数据格式的转换等。
public class OrderServiceFacade {
private final InventoryService inventoryService;
public OrderServiceFacade(InventoryService inventoryService) {
this.inventoryService = inventoryService;
}
public
2
3
4
5
6
7
8
← DDD 概念