状态模式实现订单状态流转1、问题概述2、代码实现2.1、定义环境上下文OrderContext2.2、抽象状态接口OrderState2.3、具体状态类实现3、测试1、问题概述在状态模式中我们将每一个状态都封装成一个类。状态的流转不再是一堆恶心的 if-else 或 switch-case而是让状态对象自己去决定下一个状态是谁。2、代码实现2.1、定义环境上下文OrderContext上下文负责维护当前的订单状态并暴露出触发事件的接口。publicclassOrderContext{privateLongorderId;// 持有当前的状态对象privateOrderStatestate;publicOrderContext(LongorderId){this.orderIdorderId;// 初始状态对应图中的“开始” - “待付款”this.statenewPendingPayState();}publicvoidsetState(OrderStatestate){this.statestate;}publicOrderStategetState(){returnthis.state;}// 暴露给外部业务的事件方法 //用户支付publicvoiduserPay(){state.userPay(this);}//商家发货publicvoidmerchantDeliver(){state.merchantDeliver(this);}//收到包裹publicvoidreceivePackage(){state.receivePackage(this);}//评价publicvoidcomment(){state.comment(this);}//超时未评价publicvoidcommentTimeout(){state.commentTimeout(this);}//手动取消支付publicvoidmanualCancel(){state.manualCancel(this);}//超时未支付publicvoidpayTimeout(){state.payTimeout(this);}}2.2、抽象状态接口OrderState定义所有状态的共同接口包含图中所有可能发生的动作/事件。这里使用抽象类并为所有方法提供默认实现默认抛出异常意味着当前状态不允许这个操作。publicabstractclassOrderState{// 获取当前状态名称方便打日志或存库publicabstractStringgetStateName();publicvoiduserPay(OrderContextcontext){thrownewUnsupportedOperationException(getStateName() 状态下无法执行 [用户支付]);}publicvoidmerchantDeliver(OrderContextcontext){thrownewUnsupportedOperationException(getStateName() 状态下无法执行 [商家发货]);}publicvoidreceivePackage(OrderContextcontext){thrownewUnsupportedOperationException(getStateName() 状态下无法执行 [收到包裹]);}publicvoidcomment(OrderContextcontext){thrownewUnsupportedOperationException(getStateName() 状态下无法执行 [评价]);}publicvoidcommentTimeout(OrderContextcontext){thrownewUnsupportedOperationException(getStateName() 状态下无法执行 [超时未评]);}publicvoidmanualCancel(OrderContextcontext){thrownewUnsupportedOperationException(getStateName() 状态下无法执行 [手动取消]);}publicvoidpayTimeout(OrderContextcontext){thrownewUnsupportedOperationException(getStateName() 状态下无法执行 [超时未支付]);}}2.3、具体状态类实现每个状态类只需要重写自己关心的事件。未重写的方法会直接继承父类的抛错天然做到了状态流转的安全校验。待付款状态PendingPayStatepublicclassPendingPayStateextendsOrderState{OverridepublicStringgetStateName(){return待付款;}OverridepublicvoiduserPay(OrderContextcontext){System.out.println(【业务逻辑】核心支付成功扣减真实库存...);// 流转到待发货context.setState(newPendingDeliverState());}OverridepublicvoidmanualCancel(OrderContextcontext){System.out.println(【业务逻辑】用户手动取消订单释放预扣库存...);context.setState(newCancelledState());}OverridepublicvoidpayTimeout(OrderContextcontext){System.out.println(【业务逻辑】订单支付超时系统自动取消...);context.setState(newCancelledState());}}待发货状态PendingDeliverStatepublicclassPendingDeliverStateextendsOrderState{OverridepublicStringgetStateName(){return待发货;}OverridepublicvoidmerchantDeliver(OrderContextcontext){System.out.println(【业务逻辑】商家绑定物流单号发送出库通知...);// 流转到待收货context.setState(newPendingReceiveState());}}待收货状态PendingReceiveStatepublicclassPendingReceiveStateextendsOrderState{OverridepublicStringgetStateName(){return待收货;}OverridepublicvoidreceivePackage(OrderContextcontext){System.out.println(【业务逻辑】确认收货成功资金结算给商家...);// 流转到待评价context.setState(newPendingCommentState());}}待评价状态PendingCommentStatepublicclassPendingCommentStateextendsOrderState{OverridepublicStringgetStateName(){return待评价;}Overridepublicvoidcomment(OrderContextcontext){System.out.println(【业务逻辑】写入用户评价数据发放积分奖励...);context.setState(newCompletedState());}OverridepublicvoidcommentTimeout(OrderContextcontext){System.out.println(【业务逻辑】系统超时未评默认好评...);context.setState(newCompletedState());}}5. 终态已取消CancelledState与 已完成CompletedState这两个是图中的终点它们不重写任何流转方法即任何后续操作都会报错。publicclassCancelledStateextendsOrderState{OverridepublicStringgetStateName(){return已取消(终态);}}publicclassCompletedStateextendsOrderState{OverridepublicStringgetStateName(){return已完成(终态);}}3、测试publicclassMain{publicstaticvoidmain(String[]args){// 1. 初始化订单自动进入 待付款OrderContextordernewOrderContext(10086L);System.out.println(当前订单状态order.getState().getStateName());// 2. 正常流转支付 - 发货 - 收货 - 评价order.userPay();System.out.println(当前订单状态order.getState().getStateName());order.merchantDeliver();System.out.println(当前订单状态order.getState().getStateName());order.receivePackage();System.out.println(当前订单状态order.getState().getStateName());order.comment();System.out.println(当前订单状态order.getState().getStateName());System.out.println(---------------------------------------);// 3. 测试异常流转比如在 [已完成] 状态下企图去调用 [手动取消]try{order.manualCancel();}catch(UnsupportedOperationExceptione){System.err.println(拦截非法操作成功: e.getMessage());}}}当前订单状态待付款 【业务逻辑】核心支付成功扣减真实库存...当前订单状态待发货 【业务逻辑】商家绑定物流单号发送出库通知...当前订单状态待收货 【业务逻辑】确认收货成功资金结算给商家...当前订单状态待评价 【业务逻辑】写入用户评价数据发放积分奖励...当前订单状态已完成(终态)---------------------------------------拦截非法操作成功:已完成(终态)状态下无法执行[手动取消]