DDD学习第5课应用层与领域服务

发布时间:2026/10/17 3:27:10
DDD学习第5课应用层与领域服务 第5课应用层与领域服务一、目标通过本课你将学会理解应用服务与领域服务的职责边界将复杂业务逻辑如折扣计算、库存检查提取为独立的领域服务重构OrderLifecycleService让其更“轻”二、概念回顾层级职责是否依赖领域模型示例应用层Application Service协调领域对象完成用例处理事务、权限、事件等✅ 是下单、支付、发货领域层Domain Service实现不适合放在实体或值对象中的业务规则❌ 否折扣计算、库存检查基础设施层Infrastructure负责外部资源访问数据库、API、MQ等✅ 是JPA、Redis、消息总线三、改造思路当前的OrderLifecycleServicepublicOrdercreateOrder(){OrderordernewOrder(OrderId.newId());order.addMenuItem(menu.findItem(Fried Rice),1);order.addMenuItem(menu.findItem(Coke),2);repository.save(order);returnorder;}问题业务逻辑选菜、折扣、校验都在应用层随着逻辑变复杂应用层容易臃肿Menu、Repository 等依赖太多容易造成循环依赖。我们要做的是把业务逻辑拆分为领域服务让OrderLifecycleService只负责“编排”。四、实现代码新建领域服务PricingService负责折扣计算、订单总额调整。packagecom.example.ordersystem.domain.order.service;importcom.example.ordersystem.domain.order.model.Money;importcom.example.ordersystem.domain.order.model.Order;importcom.example.ordersystem.domain.order.model.OrderItem;importorg.springframework.stereotype.Service;/** * 领域服务计算订单价格、折扣逻辑 */ServicepublicclassPricingService{/** * 根据业务规则计算订单总价 * 示例规则 * - 如果总额超过 50 元打 9 折 * - 如果包含 Coke第二瓶半价 */publicMoneycalculateTotal(Orderorder){doubletotal0;for(OrderItemitem:order.getItems()){doubleitemTotalitem.getPrice().getAmount()*item.getQuantity();// 特殊优惠Coke 第二瓶半价if(item.getName().equalsIgnoreCase(Coke)item.getQuantity()2){itemTotal-item.getPrice().getAmount()*0.5;}totalitemTotal;}// 满减折扣if(total50){total*0.9;}returnnewMoney(total);}}新建领域服务InventoryService负责库存校验通常会依赖外部仓储系统。packagecom.example.ordersystem.domain.order.service;importcom.example.ordersystem.domain.menu.model.MenuItem;importorg.springframework.stereotype.Service;/** * 领域服务库存检查 * 这里简单模拟逻辑真实系统可能连接库存微服务 */ServicepublicclassInventoryService{publicbooleancheckStock(MenuItemitem,intquantity){// 模拟可乐最多卖 100 瓶炒饭最多卖 50 份if(item.getName().equalsIgnoreCase(Coke)){returnquantity100;}if(item.getName().equalsIgnoreCase(Fried Rice)){returnquantity50;}returntrue;}}重构应用层OrderLifecycleServicepackagecom.example.ordersystem.application.order;importcom.example.ordersystem.domain.menu.model.Menu;importcom.example.ordersystem.domain.menu.model.MenuItem;importcom.example.ordersystem.domain.order.model.*;importcom.example.ordersystem.domain.order.repository.OrderRepository;importcom.example.ordersystem.domain.order.service.InventoryService;importcom.example.ordersystem.domain.order.service.PricingService;importorg.springframework.stereotype.Service;importorg.springframework.transaction.annotation.Transactional;/** * 应用服务编排订单生命周期 * 仅协调各领域对象、服务不承载具体业务逻辑 */ServicepublicclassOrderLifecycleService{privatefinalOrderRepositoryrepository;privatefinalMenumenu;privatefinalPricingServicepricingService;privatefinalInventoryServiceinventoryService;publicOrderLifecycleService(OrderRepositoryrepository,Menumenu,PricingServicepricingService,InventoryServiceinventoryService){this.repositoryrepository;this.menumenu;this.pricingServicepricingService;this.inventoryServiceinventoryService;}/** 创建订单 */TransactionalpublicOrdercreateOrder(){OrderordernewOrder(OrderId.newId());MenuItemfriedRicemenu.findItem(Fried Rice);MenuItemcokemenu.findItem(Coke);if(!inventoryService.checkStock(friedRice,1))thrownewIllegalStateException(Fried Rice 库存不足);if(!inventoryService.checkStock(coke,2))thrownewIllegalStateException(Coke 库存不足);order.addMenuItem(friedRice,1);order.addMenuItem(coke,2);// 计算总价含优惠MoneytotalpricingService.calculateTotal(order);System.out.println(订单优惠后总价total.getAmount());repository.save(order);returnorder;}/** 支付订单 */TransactionalpublicOrderpayOrder(StringorderId){Orderorderrepository.findById(newOrderId(orderId));order.pay();repository.save(order);returnorder;}/** 确认订单 */TransactionalpublicOrderconfirmOrder(StringorderId){Orderorderrepository.findById(newOrderId(orderId));order.confirm();repository.save(order);returnorder;}}五、运行与验证启动后执行POST http://localhost:8080/orders/create控制台输出订单优惠后总价18.5API 响应{id:{value:0ff7d...},status:CREATED,totalAmount:{amount:18.5}}说明PricingService正常计算InventoryService校验通过无循环依赖各层职责清晰。六、总结角色职责位置OrderLifecycleService用例编排事务、调用应用层PricingService折扣逻辑领域层InventoryService业务校验库存领域层JpaOrderRepositoryImpl数据持久化基础设施层

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询