从零构建在线点餐系统:用DDD思维拆解聚合与限界上下文
当你在餐厅扫码点餐时,是否思考过这个看似简单的操作背后隐藏着怎样的领域逻辑?本文将带你用DDD(领域驱动设计)的视角,通过构建一个真实的在线点餐系统,彻底理解聚合(Aggregate)与限界上下文(Bounded Context)这两个核心概念。
1. 需求场景分析
假设我们接到一个在线点餐系统的开发需求,核心业务流程如下:
- 顾客浏览餐厅菜单
- 将菜品加入购物车
- 提交订单并支付
- 厨房接收订单准备菜品
- 配送员取餐配送
- 顾客确认收货完成流程
关键业务规则:
- 一个订单可包含多个餐厅的菜品,但需拆分为子订单
- 订单提交后15分钟内可免费取消
- 支付超时30分钟未支付自动取消订单
- 不同菜品可能有不同的备餐时间要求
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 识别核心领域对象
通过事件风暴工作坊,我们识别出以下主要领域对象:
mermaid复制classDiagram
class MenuItem {
+String itemId
+String name
+Money price
+String description
+List~DietaryInfo~ dietaryInfos
}
class Cart {
+String cartId
+List~CartItem~ items
+addItem()
+removeItem()
}
class Order {
+String orderId
+OrderStatus status
+List~OrderLine~ lines
+submit()
+cancel()
}
class KitchenTicket {
+String ticketId
+List~TicketItem~ items
+markPrepared()
}
MenuItem "1" -- "*" CartItem
Cart "1" -- "*" CartItem
Order "1" -- "*" OrderLine
KitchenTicket "1" -- "*" TicketItem
3. 划定聚合边界
聚合是DDD中最具实操价值的概念之一,它定义了数据修改的单元边界。在我们的点餐系统中,可以识别出以下聚合:
3.1 菜单聚合(Menu Aggregate)
聚合根:Menu
包含对象:
- MenuItem(实体)
- Category(值对象)
- DietaryInfo(值对象)
不变条件:
- 菜单项价格不能为负
- 同一分类下的菜单项名称必须唯一
java复制public class Menu {
private String restaurantId;
private List<MenuItem> items = new ArrayList<>();
public void addItem(String name, Money price, String category) {
if (price.isNegative()) {
