DDD 战术设计详解与实例
DDD 的战术设计关注如何在具体实现中应用领域模型的原则,包括聚合、服务、工厂等设计模式。以下是每个核心概念的详细介绍和实例。
1 聚合 (Aggregate)
定义:聚合是一组相关联的对象,它们共同表现一个一致的业务规则。聚合通过聚合根进行访问,聚合根是唯一的入口点。
示例:
- 在电商系统中,一个“订单”聚合可能包含“订单项”、“支付信息”和“配送地址”。
Order
类作为聚合根,管理整个聚合的生命周期和状态。对订单的所有操作都必须通过Order
类进行,例如添加订单项或更新支付信息。
2 聚合根 (Aggregate Root)
定义:聚合根是聚合的唯一入口,外部只能通过聚合根来访问聚合内的对象。
示例:
- 在一个社交网络应用中,
User
是一个聚合根。用户可以拥有多个Post
(帖子),但外部系统只能通过User
类来访问或修改帖子。这样可以确保所有对帖子做的操作都遵循用户的业务逻辑,比如检查权限等。
3 工厂 (Factory)
定义:工厂是用于创建复杂对象的设计模式,特别是在创建过程中涉及多个步骤或需要聚合的对象时。
示例:
- 在电商系统中,当用户下单时,创建一个新的订单可能需要多个步骤,比如验证库存、生成唯一的订单号、初始化订单项等。这时可以使用
OrderFactory
,负责处理这些步骤并创建完整的Order
对象。
public class OrderFactory {public Order createOrder(List<Item> items) {// 逻辑:验证库存,生成订单号等return new Order(orderId, items);}
}
4 服务 (Service)
定义:服务是封装业务逻辑的对象,通常用于处理跨多个聚合的业务操作。服务可以是领域服务或应用服务。
示例:
- 在电商系统中,
PaymentService
可以作为领域服务,负责处理支付操作。这个服务可以被多个聚合调用,比如订单聚合和用户聚合,都可能需要调用支付服务来完成支付。
public class PaymentService {public void processPayment(Order order, PaymentInfo paymentInfo) {// 处理支付逻辑}
}
5 领域服务 (Domain Service)
定义:领域服务是处理与多个聚合相关的复杂业务逻辑,但不属于任何特定聚合的服务。
示例:
- 在电商系统中,
ShippingService
作为领域服务,负责处理订单的发货流程。它可能需要访问订单聚合和库存聚合,以确定产品是否可以发货。
6 应用服务 (Application Service)
定义:应用服务是负责协调领域对象的操作,以满足用户请求的服务,通常涉及多个领域服务的调用。
示例:
- 在电商系统中,
OrderApplicationService
负责处理用户创建订单的请求。它会调用OrderFactory
来创建订单,并调用PaymentService
来处理支付。
public class OrderApplicationService {public void createOrder(List<Item> items, PaymentInfo paymentInfo) {Order order = orderFactory.createOrder(items);paymentService.processPayment(order, paymentInfo);}
}
7 事件 (Event)
定义:领域事件是表示领域中重要状态变化的事件。它们可以用于触发其他系统或服务的反应。
示例:
- 在电商系统中,当订单状态从“待支付”变为“已支付”时,可以发布一个名为
OrderPaidEvent
的领域事件。这可以触发物流系统开始发货流程。
8 仓储 (Repository)
定义:仓储用于持久化和检索聚合根,提供一个抽象接口,使得业务逻辑与数据存储分离。
示例:
- 在电商系统中,
OrderRepository
用于存储和检索订单聚合。开发人员可以通过OrderRepository
来获取订单数据,而不必直接与数据库交互。
public interface OrderRepository {Order findById(OrderId id);void save(Order order);
}
示例总结:
通过这些战术设计的概念,DDD 提供了一套结构化的方法来设计复杂业务系统。以下是这些概念在电商系统中的具体运用:
- 聚合:订单聚合管理订单及其项。
- 聚合根:用户作为聚合根管理帖子。
- 工厂:
OrderFactory
创建订单对象。 - 服务:
PaymentService
处理支付逻辑。 - 领域服务:
ShippingService
处理发货。 - 应用服务:
OrderApplicationService
协调订单创建流程。 - 事件:
OrderPaidEvent
通知系统状态变化。 - 仓储:
OrderRepository
处理订单存取。
DEMO:
完整 Java 示例:聚合、聚合根、工厂、服务、领域服务、应用服务、事件、仓储的调用关系
在这个完整示例中,我们将展示一个简化的电商订单系统,涵盖聚合、聚合根、工厂、服务、领域服务、应用服务、事件和仓储之间的相互关系。
场景:用户在系统中创建一个订单,完成支付后发起发货,并触发发货通知事件。
1. 聚合与聚合根:Order(订单)和 OrderItem(订单项)
public class Order {private String orderId;private List<OrderItem> items;private OrderStatus status;public Order(String orderId, List<OrderItem> items) {this.orderId = orderId;this.items = items;this.status = OrderStatus.CREATED;}public void addOrderItem(OrderItem item) {this.items.add(item);}public void pay() {this.status = OrderStatus.PAID;}public boolean isPaid() {return this.status == OrderStatus.PAID;}public String getOrderId() {return orderId;}public List<OrderItem> getItems() {return items;}
}public class OrderItem {private String productId;private int quantity;public OrderItem(String productId, int quantity) {this.productId = productId;this.quantity = quantity;}public String getProductId() {return productId;}public int getQuantity() {return quantity;}
}
2. 工厂:OrderFactory
public class OrderFactory {public Order createOrder(List<OrderItem> items) {String orderId = UUID.randomUUID().toString();return new Order(orderId, items);}
}
3. 服务:PaymentService(支付服务)
public class PaymentService {public void processPayment(Order order, PaymentInfo paymentInfo) {// 支付处理逻辑System.out.println("Processing payment for order: " + order.getOrderId());order.pay();}
}
4. 领域服务:ShippingService(发货服务)
public class ShippingService {public void shipOrder(Order order) {if (order.isPaid()) {System.out.println("Shipping order: " + order.getOrderId());// 发货逻辑} else {System.out.println("Order not paid, cannot ship.");}}
}
5. 应用服务:OrderApplicationService(订单应用服务)
public class OrderApplicationService {private OrderFactory orderFactory;private PaymentService paymentService;private ShippingService shippingService;private OrderRepository orderRepository;private EventPublisher eventPublisher;public OrderApplicationService(OrderFactory orderFactory, PaymentService paymentService, ShippingService shippingService, OrderRepository orderRepository, EventPublisher eventPublisher) {this.orderFactory = orderFactory;this.paymentService = paymentService;this.shippingService = shippingService;this.orderRepository = orderRepository;this.eventPublisher = eventPublisher;}public void createOrder(List<OrderItem> items, PaymentInfo paymentInfo) {// 使用工厂创建订单Order order = orderFactory.createOrder(items);orderRepository.save(order);// 处理支付paymentService.processPayment(order, paymentInfo);// 发货shippingService.shipOrder(order);// 触发发货事件eventPublisher.publish(new OrderShippedEvent(order.getOrderId()));}
}
6. 事件:OrderShippedEvent(订单发货事件)
public class OrderShippedEvent {private String orderId;public OrderShippedEvent(String orderId) {this.orderId = orderId;}public String getOrderId() {return orderId;}
}
7. 事件发布器:EventPublisher(事件发布器)
public class EventPublisher {public void publish(OrderShippedEvent event) {// 事件发布逻辑System.out.println("Order shipped event published for order: " + event.getOrderId());}
}
8. 仓储:OrderRepository(订单仓储)
public interface OrderRepository {Order findById(String orderId);void save(Order order);
}public class InMemoryOrderRepository implements OrderRepository {private Map<String, Order> database = new HashMap<>();@Overridepublic Order findById(String orderId) {return database.get(orderId);}@Overridepublic void save(Order order) {database.put(order.getOrderId(), order);System.out.println("Order saved: " + order.getOrderId());}
}
完整调用流程:
- 用户请求创建订单。
OrderApplicationService
调用OrderFactory
创建Order
对象。- 创建的
Order
保存到OrderRepository
。 OrderApplicationService
调用PaymentService
处理支付。- 如果支付成功,
OrderApplicationService
调用ShippingService
处理发货。 OrderApplicationService
通过EventPublisher
发布OrderShippedEvent
,通知系统订单已发货。
示例总结:
- 聚合与聚合根:
Order
和OrderItem
构成了订单聚合,Order
作为聚合根管理聚合内部的状态和操作。 - 工厂:
OrderFactory
负责创建订单,封装了创建复杂对象的逻辑。 - 服务:
PaymentService
负责处理订单的支付。 - 领域服务:
ShippingService
负责处理订单的发货流程。 - 应用服务:
OrderApplicationService
协调各个组件来完成订单创建、支付和发货的流程。 - 事件:
OrderShippedEvent
表示订单已发货,并通过EventPublisher
进行通知。 - 仓储:
OrderRepository
负责订单的持久化和检索。
这个完整的例子展示了 DDD 中各个战术设计元素如何相互配合,构建一个清晰的业务系统。