Java 23 种设计模式:从踩坑到精通 | 番外:状态 vs 策略 —— if-else 消除的两条路,你走对了吗?

发布时间:2026/7/13 19:00:04

Java 23 种设计模式:从踩坑到精通 | 番外:状态 vs 策略 —— if-else 消除的两条路,你走对了吗? Java 23 种设计模式从踩坑到精通 | 番外状态 vs 策略 —— if-else 消除的两条路你走对了吗摘要状态模式和策略模式都能消除if-else都通过多态将不同逻辑封装到独立类中。但它们的核心区别在于谁来决定切换——状态模式中状态对象自己决定下一步流转策略模式中客户端主动选择算法。本文从订单状态流转和促销策略计算两个实战场景出发结合代码对比、UML 分析和 Spring State Machine 源码帮你彻底分清这对“行为型双胞胎”。️本文阅读地图3 分钟速览为什么状态和策略都能消除 if-else它们到底像在哪里一张表看懂意图、切换方式、上下文感知的全面对比手写订单状态机 vs 促销策略引擎感受差异Spring State Machine 如何体现代状态模式面试必问“状态模式和策略模式怎么区分能配合使用吗”《Java 23 种设计模式从踩坑到精通》开篇系列介绍与目录 当前番外 · 状态 vs 策略 返回系列总目录文章目录Java 23 种设计模式从踩坑到精通 | 番外状态 vs 策略 —— if-else 消除的两条路你走对了吗1. 从“订单处理”和“促销计算”两个场景说起1.1 场景一订单状态流转状态模式1.2 场景二促销策略计算策略模式2. UML 对比结构相似意图不同2.1 状态模式 UML2.2 策略模式 UML3. 三大核心区别4. 深入理解Spring State Machine 如何体现代状态模式5. 状态和策略能配合使用吗6. 面试必问 追问连环炮 《Java 23 种设计模式从踩坑到精通》快速导航1. 从“订单处理”和“促销计算”两个场景说起1.1 场景一订单状态流转状态模式订单有“待支付”、“已支付”、“已发货”、“已完成”等状态。每个状态下用户能执行的操作不同。如果用if-else判断当前状态再执行操作代码会迅速膨胀。我们选择状态模式。// 状态模式状态对象自己决定下一步publicclassPaidStateimplementsOrderState{Overridepublicvoidship(OrderContextcontext){System.out.println(订单已发货);context.setState(newShippedState());// 状态对象自己决定切换到“已发货”}Overridepublicvoidcancel(OrderContextcontext){thrownewIllegalStateException(已支付订单无法取消请申请退款);}}1.2 场景二促销策略计算策略模式促销有“满减”、“打折”、“立减”等多种算法。用户下单时需要根据促销类型计算价格。我们选择策略模式。// 策略模式客户端选择策略OrderordernewOrder(500);order.setPromotionStrategy(newFullReductionStrategy());// 客户端主动选择doublepriceorder.checkout();关键差异已浮现状态模式中PaidState自己在ship()方法中调用context.setState()切换到下一个状态状态对象控制流转。策略模式中客户端调用setPromotionStrategy()传入具体策略客户端控制选择。2. UML 对比结构相似意图不同2.1 状态模式 UML2.2 策略模式 UMLUML 的关键差异状态模式的Context提供setState()方法由状态对象在handle()中调用策略模式的Context提供setStrategy()方法由客户端调用状态类之间通常有明确的转换关系策略类之间完全独立。3. 三大核心区别对比维度状态模式策略模式意图让对象的行为随内部状态自动改变封装一系列算法使其可相互替换谁决定切换状态对象自己决定何时切换到另一个状态客户端显式选择策略上下文感知状态对象持有Context引用可调用context.setState()策略对象通常不知道Context的存在类间关系状态类之间有明确的转换关系如待支付→已支付→已发货策略类之间完全独立互不感知典型应用订单状态机、线程状态、工单流转支付方式、排序算法、折扣策略简单记忆状态模式是“被动流转”——状态对象自己决定下一步策略模式是“主动选择”——客户端选择算法。4. 深入理解Spring State Machine 如何体现代状态模式Spring State Machine 是一个专门的状态机框架它通过配置定义状态和事件由引擎管理状态流转。这本质上就是状态模式的升级版本。ConfigurationEnableStateMachinepublicclassOrderStateMachineConfigextendsStateMachineConfigurerAdapterString,String{Overridepublicvoidconfigure(StateMachineStateConfigurerString,Stringstates)throwsException{states.withStates().initial(待支付).state(已支付).state(已发货).end(已完成).end(已取消);}Overridepublicvoidconfigure(StateMachineTransitionConfigurerString,Stringtransitions)throwsException{transitions.withExternal().source(待支付).target(已支付).event(支付).and().withExternal().source(待支付).target(已取消).event(取消).and().withExternal().source(已支付).target(已发货).event(发货).and().withExternal().source(已发货).target(已完成).event(确认收货);}}为什么是状态模式状态的流转由状态机引擎控制类比状态对象自己决定下一步每个状态下的合法操作通过配置明确类比状态对象内部的判断逻辑外部只需触发事件无需关心当前处于哪个状态类比客户端只调用context.request()。5. 状态和策略能配合使用吗当然可以。订单状态决定“什么时候该结算”促销策略决定“用什么算法结算”。// 在已支付状态中调用策略模式计算最终价格publicclassPaidStateimplementsOrderState{Overridepublicvoidcheckout(OrderContextcontext,PromotionStrategystrategy){doublefinalPricestrategy.calculate(context.getOrder());context.setTotalPrice(finalPrice);// ... 完成结算进入下一状态}}组合方式状态决定“什么时候做”策略决定“怎么做”。两者解耦各自独立变化。6. 面试必问 追问连环炮基础必问状态模式和策略模式的区别 状态模式状态对象自己决定切换被动流转策略模式由客户端显式选择主动替换。JDK 哪里用了状态模式 线程的状态转换NEW → RUNNABLE → WAITING → BLOCKED → TERMINATED。面试官追问“状态模式中状态类为什么要持有上下文引用” 以便在需要流转时调用context.setState()切换到新状态。策略模式不需要因为策略只关心算法本身。“如果状态转换逻辑很复杂状态类会膨胀怎么办” 使用状态机框架如 Spring State Machine将状态、事件、转换规则配置化避免手写大量状态类。“状态模式和策略模式能配合使用吗” 可以。状态决定“何时执行”策略决定“如何执行”。如订单状态决定该结算了策略决定用满减还是打折。“策略模式如何消除 if-else” 将每个分支算法封装为独立的策略类通过多态调用。但策略的选择本身可能仍需一个if-else或工厂来根据条件创建具体策略实例——这部分可以交给策略工厂处理。恭喜如果你能立刻说出“状态自己决定流转策略由客户端选择”并画出状态流转图与策略对比图你已经掌握了行为型模式中最核心的区分点。延伸阅读本文是状态模式与策略模式的深度对比。如果你想先了解每种模式的完整原理、UML、代码实现和面试题可以先阅读正篇——状态模式if-else 满天飞让状态自己决定行为 和 策略模式算法族的封装与切换告别 if-else再回来看这篇对比效果更佳。 《Java 23 种设计模式从踩坑到精通》快速导航开篇系列介绍与目录当前番外 · 状态 vs 策略 —— if-else 消除的两条路你走对了吗你在这里 延伸阅读状态模式正篇 策略模式正篇创建型模式汇总结构型模式汇总行为型模式汇总 关注《Java 23 种设计模式从踩坑到精通》用 25 篇文章彻底吃透设计模式。福利预告全系列代码及 UML 源码将在完结时统一打包开放点击「关注」「收藏」第一时间获取。 除了设计模式我也在深挖智能物流实战WMS、托盘调度、机器学习落地。欢迎点击头像看看专栏 《出版社物流WMS智能调度实战》。技术相通思路可鉴。

相关新闻