前言
最初设计出这个解决方案的初衷,也是因为在项目开发的过程中,订单有各种状态,状态流转做的事情都不一样,而且不同的状态到目标状态有很多种途径.
C端、管理平台、商家后台等服务都可以去操作订单状态。这样就需要写很多个service,在各个需要的地方去调用。这样就导致业务逻辑不怎么清晰,我就像能不能做一个统一的入口,通过某个标识去判断,要做什么事,订单要流转到什么状态。
然后我就了解到了状态模式,然后衍生出状态机模式,当然这个设计其实这不完全算是状态模式,只是用状态模式的思想,事件驱动状态流转。
个人总结的一些经验,希望能对你有所帮助,如果有什么好的意见或者建议,欢迎指点。
什么是状态模式?
(源于Design Pattern):当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。
基于这个定义,我就想,订单的状态不是刚好符合吗,每个状态的订单,可能对应了不同的行为。例如待支付状态的订单,它可以取消订单、也可以支付订单。所以我就想到了根据事件驱动行为
我的理解的状态机
-
状态机可归纳为4个要素,即现态、事件、动作、次态。详解如下:
①现态:是指当前对象所处的状态。
②事件:也可称为"条件"。当一个条件被满足,将会触发一个动作,或者执行一次状态的迁移。
③动作:条件满足后执行的动作,动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作不是必需的,当条件满足后,也可以不执行任何动作,直接迁移到目标状态。
④次态:条件满足后要迁往的目标状态。“次态”是相对于“现态”而言的,“次态”一旦被激活,对象就转变成新的“现态”了。
-
状态机就是将驱动类,根据当前状态得到对应的执行者,执行者再根据指定事件,做对应动作,将当前状态改变为目标状态
驱动类可以用同一个对象,也可以根据不同的事件操作使用不同的对象,例如订单审核没有其他个性化参数,就可以直接用公共的驱动者。
再比如支付回调,将未支付改为待审核,就有支付时间这样个性化的参数,就可以用SaleOrderPayEventDriver驱动
状态机实践
//驱动者-->设置当前订单状态-->得到行动队长-->执行期望动作
//审核订单,状态流转到待发货。详细可参考OrderController.java 37行
saleOrderEventDriver.status(SaleOrderStatusEnum.WAITING_AUDIT.getCode())
.handle(SaleOrderEventEnum.AUDIT_TO_DELIVER);
状态设计的一点建议
- 事件编码需要有间隙,便于插入子事件,状态枚举也是,便于插入子状态或者中间状态