2026/7/29 23:10:04

Java 23 种设计模式:从踩坑到精通 | 番外:外观模式 —— 物流订单处理实战

Java 23 种设计模式:从踩坑到精通 | 番外:外观模式 —— 物流订单处理实战 Java 23 种设计模式从踩坑到精通 | 番外外观模式 —— 物流订单处理实战摘要外观模式为子系统中的一组接口提供一个统一的高层接口让客户端只需一键操作即可完成原本需要多次调用的复杂流程。本文结合**智能物流中“订单处理系统”**的场景完整展示如何用外观模式封装订单校验、库存扣减、支付处理、配送调度、消息通知等五个子系统的协作让你彻底掌握“化繁为简”的设计精髓。️本文阅读地图3 分钟速览为什么下单流程不能直接暴露给客户端✅ 外观模式核心角色外观类与子系统手写物流订单门面一行代码完成下单、取消 外观 vs 适配器简化 vs 转换 面试必问“外观模式和适配器模式有什么区别”《Java 23 种设计模式从踩坑到精通》开篇系列介绍与目录 正篇外观模式 Facade —— 给复杂系统装一个“一键启动” 当前番外 · 外观模式 × 物流订单处理 返回系列总目录1. 物流订单处理的复杂流程在智能物流系统中一个简单的下单操作背后涉及订单校验、库存检查、支付处理、运费计算、揽收调度、短信通知等多个子系统。如果让客户端直接调用这些子系统代码会变得臃肿且耦合严重// 客户端直接调用子系统步骤多、易遗漏、难维护OrderServiceorderServicenewOrderService();PaymentServicepaymentServicenewPaymentService();InventoryServiceinventoryServicenewInventoryService();ShippingServiceshippingServicenewShippingService();NotificationServicenotificationServicenewNotificationService();if(orderService.validateOrder(info)){if(inventoryService.checkStock(sku,quantity)){OrderorderorderService.createOrder(info);doublefeeshippingService.calculateShippingFee(address,weight);PaymentResultpaypaymentService.processPayment(order,fee);if(pay.isSuccess()){inventoryService.deductStock(sku,quantity);shippingService.schedulePickup(order);notificationService.sendShipmentNotice(order,user);}}}外观模式的解决思路提供一个统一的LogisticsOrderFacade外观类把上述复杂流程封装在placeOrder()方法中。客户端只需调用一次外观方法无需关心内部有多少子系统、调用顺序如何、出错如何处理。1.1 你的场景该不该用外观判断标准是 → 用外观否 → 用其他方式需要为多个子系统提供统一入口✅❌子系统复杂调用步骤多✅❌希望降低客户端与子系统的耦合✅❌子系统简单只有一两个类❌直接调用即可2. 外观模式 UML物流订单处理场景3. 完整源码实现3.1 子系统A订单服务 (OrderService)importjava.util.UUID;publicclassOrderService{publicbooleanvalidateOrder(OrderInfoinfo){System.out.println( 订单服务校验订单信息...);if(info.getSku()null||info.getSku().isEmpty()||info.getQuantity()0||info.getAddress()null){System.out.println( ❌ 订单服务校验失败);returnfalse;}System.out.println( ✅ 订单服务校验通过);returntrue;}publicOrdercreateOrder(OrderInfoinfo){OrderordernewOrder(UUID.randomUUID().toString(),info);order.setStatus(OrderStatus.CREATED);System.out.printf( ✅ 订单服务订单创建成功 | 订单号%s\n,order.getOrderId());returnorder;}publicvoidupdateOrderStatus(StringorderId,OrderStatusstatus){System.out.printf( 订单服务订单[%s]状态更新为 %s\n,orderId,status);}}// 支撑类classOrder{privateStringorderId;privateOrderInfoinfo;privateOrderStatusstatus;// 构造器与 getter/setter 省略...}classOrderInfo{privateStringsku;privateintquantity;privateStringaddress;privatedoubleweight;// 构造器与 getter 省略...}enumOrderStatus{CREATED,PAID,SHIPPED,COMPLETED,CANCELLED,FAILED}白话订单服务只关心订单的验证与状态变更不涉及支付或物流。3.2 子系统B支付服务 (PaymentService)publicclassPaymentService{publicPaymentResultprocessPayment(Orderorder,doubleamount){System.out.printf( 支付服务处理支付 | 订单[%s] | 金额¥%.2f\n,order.getOrderId(),amount);System.out.printf( ✅ 支付服务支付成功\n);returnnewPaymentResult(true,PAYSystem.currentTimeMillis());}publicbooleanrefund(StringorderId,doubleamount){System.out.printf( 支付服务退款成功 | 订单[%s]\n,orderId);returntrue;}}classPaymentResult{privatebooleansuccess;privateStringpaymentId;// 构造器...}3.3 子系统C库存服务 (InventoryService)importjava.util.Map;importjava.util.concurrent.ConcurrentHashMap;publicclassInventoryService{privatefinalMapString,IntegerstockMapnewConcurrentHashMap();publicInventoryService(){stockMap.put(SKU001,100);stockMap.put(SKU002,50);stockMap.put(SKU003,200);}publicbooleancheckStock(Stringsku,intquantity){intcurrentstockMap.getOrDefault(sku,0);booleanokcurrentquantity;System.out.printf( 库存服务检查库存 | SKU[%s] | %s\n,sku,ok?充足:不足);returnok;}publicvoiddeductStock(Stringsku,intquantity){stockMap.computeIfPresent(sku,(k,v)-v-quantity);System.out.printf( ✅ 库存服务扣减成功 | SKU[%s] -%d\n,sku,quantity);}publicvoidrestoreStock(Stringsku,intquantity){stockMap.computeIfPresent(sku,(k,v)-vquantity);System.out.printf( ✅ 库存服务恢复库存 | SKU[%s] %d\n,sku,quantity);}}3.4 子系统D配送服务 (ShippingService)publicclassShippingService{publicdoublecalculateShippingFee(Stringaddress,doubleweight){doublefee10.0Math.max(0,weight-1)*5;System.out.printf( 配送服务运费 | 地址%s | 费用¥%.2f\n,address,fee);returnfee;}publicShipmentschedulePickup(Orderorder){StringtrackingNoTRKSystem.currentTimeMillis();System.out.printf( ✅ 配送服务已安排揽收 | 运单号%s\n,trackingNo);returnnewShipment(trackingNo,order.getOrderId());}}classShipment{/* trackingNo, orderId */}enumShipmentStatus{PENDING,PICKED_UP,IN_TRANSIT,DELIVERED}3.5 子系统E通知服务 (NotificationService)publicclassNotificationService{publicvoidsendOrderConfirmation(Orderorder,Stringuser){System.out.printf( 通知订单确认 → 用户[%s]\n,user);}publicvoidsendPaymentSuccess(Orderorder,Stringuser){System.out.printf( 通知支付成功 → 用户[%s]\n,user);}publicvoidsendShipmentNotice(Orderorder,Stringuser){System.out.printf( 通知已发货 → 用户[%s]\n,user);}publicvoidsendOrderCancelled(Orderorder,Stringuser){System.out.printf( 通知订单取消 → 用户[%s]\n,user);}}3.6 外观类物流订单门面 (LogisticsOrderFacade)publicclassLogisticsOrderFacade{privatefinalOrderServiceorderServicenewOrderService();privatefinalPaymentServicepaymentServicenewPaymentService();privatefinalInventoryServiceinventoryServicenewInventoryService();privatefinalShippingServiceshippingServicenewShippingService();privatefinalNotificationServicenotificationServicenewNotificationService();publicOrderResultplaceOrder(OrderInfoorderInfo,Stringuser){System.out.println(\n 开始处理下单...);// 1. 校验 库存if(!orderService.validateOrder(orderInfo))returnOrderResult.failure(校验失败);if(!inventoryService.checkStock(orderInfo.getSku(),orderInfo.getQuantity()))returnOrderResult.failure(库存不足);// 2. 创建订单 通知OrderorderorderService.createOrder(orderInfo);notificationService.sendOrderConfirmation(order,user);// 3. 运费 支付doubleshippingFeeshippingService.calculateShippingFee(orderInfo.getAddress(),orderInfo.getWeight());doubletotal99.99*orderInfo.getQuantity()shippingFee;PaymentResultpaypaymentService.processPayment(order,total);if(!pay.isSuccess()){orderService.updateOrderStatus(order.getOrderId(),OrderStatus.FAILED);returnOrderResult.failure(支付失败);}orderService.updateOrderStatus(order.getOrderId(),OrderStatus.PAID);notificationService.sendPaymentSuccess(order,user);// 4. 扣减库存 配送inventoryService.deductStock(orderInfo.getSku(),orderInfo.getQuantity());ShipmentshipmentshippingService.schedulePickup(order);notificationService.sendShipmentNotice(order,user);orderService.updateOrderStatus(order.getOrderId(),OrderStatus.SHIPPED);System.out.println(✅ 下单完成);returnOrderResult.success(order.getOrderId(),pay.getPaymentId(),shipment.getTrackingNo());}publicbooleancancelOrder(StringorderId,Stringuser){System.out.println(\n 取消订单...);paymentService.refund(orderId,99.99);orderService.updateOrderStatus(orderId,OrderStatus.CANCELLED);notificationService.sendOrderCancelled(newOrder(orderId,null),user);System.out.println(✅ 取消完成);returntrue;}}classOrderResult{/* success, orderId, paymentId, trackingNo, errorMsg */}白话外观类的placeOrder就像前台接待客户说“我要下单”它就会按固定流程走完所有环节客户完全不需知道背后有多少个部门在协作。3.7 客户端测试publicclassClient{publicstaticvoidmain(String[]args){LogisticsOrderFacadefacadenewLogisticsOrderFacade();// 正常下单OrderResultr1facade.placeOrder(newOrderInfo(SKU001,2,北京市朝阳区,3.5),张三);if(r1.isSuccess()){System.out.printf(订单号%s, 运单号%s\n,r1.getOrderId(),r1.getTrackingNo());}// 库存不足OrderResultr2facade.placeOrder(newOrderInfo(SKU999,1000,上海市,1.0),李四);if(!r2.isSuccess())System.out.println(失败原因r2.getErrorMsg());// 取消订单facade.cancelOrder(r1.getOrderId(),张三);}}4. 运行结果 开始处理下单... 订单服务校验订单信息... ✅ 库存服务检查库存 | SKU[SKU001] | 充足 ✅ 订单服务订单创建成功 通知订单确认 → 用户[张三] 配送服务运费 | 费用¥22.50 支付服务支付成功 订单服务状态更新为 PAID 通知支付成功 → 用户[张三] ✅ 库存服务扣减成功 ✅ 配送服务已安排揽收 | 运单号TRK... 通知已发货 → 用户[张三] 订单服务状态更新为 SHIPPED ✅ 下单完成 订单号..., 运单号TRK... 开始处理下单... 库存服务检查库存 | SKU[SKU999] | 不足 失败原因库存不足 取消订单... 支付服务退款成功 订单服务状态更新为 CANCELLED 通知订单取消 → 用户[张三] ✅ 取消完成5. 核心角色回顾角色职责对应代码Facade统一入口封装流程LogisticsOrderFacadeSubsystem独立处理各自业务逻辑OrderService,PaymentService,InventoryService,ShippingService,NotificationService6. 外观模式 vs 适配器模式对比项外观模式适配器模式意图简化接口隐藏复杂性转换接口让不兼容的类协同工作关注点降低客户端调用难度解决接口不兼容问题子系统感知子系统不知道外观的存在适配器持有被适配者被适配者不知道适配器典型应用物流订单门面、JdbcTemplateInputStreamReader、对接第三方快递API一句话记忆外观是“一键启动”——把复杂流程变成一个方法适配器是“转接头”——把不兼容的接口转成你想要的格式。7. 外观模式的优缺点优点缺点简化客户端调用降低耦合可能成为“上帝类”所有请求都经过外观保护子系统客户端不会误用危险方法新增子系统可能需要修改外观类分层清晰可作为层间解耦手段高级用户可能被隐藏了有用的子系统细节8. 六大设计原则体现原则体现单一职责外观类只负责流程编排不实现具体业务开闭原则新增子系统可能需要修改外观但可结合工厂缓解里氏替换子系统可替换升级不影响外观依赖倒置客户端依赖外观抽象接口可进一步解耦接口隔离外观提供精简的高层接口避免“胖接口”迪米特法则客户端只与外观交互符合最少知识原则附 外观模式 UML源码物流订单处理场景startuml title Java 23 种设计模式从踩坑到精通 footer 折哥 | 智能物流与Java实战 1. 全局样式配置 skinparam backgroundColor #FEFEFE skinparam shadowing false skinparam defaultFontName Microsoft YaHei skinparam classBorderColor #333333 skinparam classFontColor #1A1A1A skinparam classFontSize 14 skinparam noteFontSize 12 skinparam noteFontColor #555555 skinparam arrowColor #555555 skinparam classBackgroundColor #F9F9F9 2. 外观类 - 物流订单门面 class LogisticsOrderFacade { - orderService : OrderService - paymentService : PaymentService - inventoryService : InventoryService - shippingService : ShippingService - notificationService : NotificationService placeOrder(orderInfo) : OrderResult cancelOrder(orderId) : boolean } note right of LogisticsOrderFacade b外观类物流订单门面/b -- 为客户端提供统一的下单入口 封装内部多个子系统的复杂调用流程 客户端无需了解内部细节 end note 3. 子系统类 class OrderService { validateOrder(info) : boolean createOrder(info) : Order updateOrderStatus(id, status) } note right of OrderService b子系统A订单服务/b -- 负责订单校验、创建、状态更新 end note class PaymentService { processPayment(order, amount) : PaymentResult refund(orderId, amount) : boolean } note right of PaymentService b子系统B支付服务/b -- 负责支付处理、退款 end note class InventoryService { checkStock(sku, quantity) : boolean deductStock(sku, quantity) restoreStock(sku, quantity) } note right of InventoryService b子系统C库存服务/b -- 负责库存检查、扣减、恢复 end note class ShippingService { calculateShippingFee(address, weight) : double schedulePickup(order) : Shipment trackShipment(trackingNo) : ShipmentStatus } note right of ShippingService b子系统D配送服务/b -- 负责运费计算、揽收调度、物流跟踪 end note class NotificationService { sendOrderConfirmation(order, user) sendPaymentSuccess(order, user) sendShipmentNotice(order, user) sendOrderCancelled(order, user) } note bottom of NotificationService b子系统E通知服务/b -- 负责短信、邮件、站内信通知 end note 4. 关系连线 LogisticsOrderFacade -- OrderService : 委托 LogisticsOrderFacade -- PaymentService : 委托 LogisticsOrderFacade -- InventoryService : 委托 LogisticsOrderFacade -- ShippingService : 委托 LogisticsOrderFacade -- NotificationService : 委托 enduml 《Java 23 种设计模式从踩坑到精通》快速导航开篇系列介绍与目录正篇外观模式 Facade —— 给复杂系统装一个“一键启动”当前番外 · 外观模式 × 物流订单处理你在这里创建型模式汇总结构型模式汇总行为型模式汇总 关注《Java 23 种设计模式从踩坑到精通》用 25 篇文章彻底吃透设计模式。福利预告全系列代码及 UML 源码将在完结时统一打包开放点击「关注」「收藏」第一时间获取。 除了设计模式我也在深挖智能物流实战WMS、托盘调度、机器学习落地。欢迎点击头像看看专栏 《出版社物流WMS智能调度实战》、《电商多平台电子面单对接实战》。技术相通思路可鉴。