订单状态机设计

本文探讨了状态机设计的基本要素与流程,包括状态、事件、流转等,并深入讨论了条件动态设计,选择了MVEL表达式语言。同时,文章对比分析了Drools、EasyRules和RuleBook作为规则引擎的优劣,最终推荐EasyRules用于实现状态机的分叉场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

状态机整体设计:

 

说明:

  1. 基本要素:状态(state)、事件(event)、流转(transition)、虚拟状态(virtual state)、条件(guard)、条件分支、默认分支;
  2. 基本流程:图中"开始"状态接收到事件"E1"后切换至"S1"状态,完成一次状态流转;
  3. 自转场景:图中"S1"接收"E11"后状态未发生改变,同样视为完整一次状态流转;
  4. 分叉场景:图中"S1"到"S21"或"S22"的状态实际流转需要根据不同的条件选择,这里插入一个虚拟状态"选择状态1","S1"到"选择状态1"的流转由事件"E2"触发,而"选择状态1"到"S21"或"S22"的流转则由于虚拟状态的存在自动进行;
  5. 子任务场景:图中"S3"到"S4"的流转需要多个"E4"事件触发,这里同样插入虚拟状态"选择状态2"来实现,不同的是将默认分支回溯到"S3"。

单个流程详细实现

1.同步调用

2.异步调用


图中按时间顺序包含两个部分:业务端发送事件并返回结果、状态机处理事件回调业务系统完成状态流转,两个部分分别在两个数据库事务中。

条件动态设计方案——表达式语言

       状态机的应用需要各自业务系统根据自身的业务逻辑动态设计,对于状态机中逻辑条件的实现,这里选择使用java表达式语言,备选方案有Spring Expression Language(以下简称SpEL)和MVEL。
        根据官方文档介绍,SpEL的诞生是为了给Spring社区提供一种能够与Spring生态系统所有产品无缝对接,能提供一站式支持的表达式语言。考虑到Spring的框架的应用,SpEL是是最合适的选择,后续研究发现在以下场景中支持不友好:订单存在子订单,并且订单状态需要根据所有子订单的信息来综合考虑流转情况,SpEL实现遍历集合的方案是通过注册函数使用Java Stream的方式,与MVEL支持原生foreach循环相比复杂极大提高,而考虑到状态机条件使用场景,最终选择MVEL的方式。

状态机设计交互数据格式

{

    "smInfo": {

        "smId"null// long 状态机id,保存时需要,新增时为空

        "flowId"null// long 流程id

        "version"null// string 版本

        "smStatus"null// integer 状态机状态(1:测试中,2:已发布,3:已上线,4:已停用)

        "creator"null// string 创建人

        "modifier"null // string 修改人

    },

    "smStates": [{

        "stateId"null// long 状态id,保存时需要,新增时为空

        "stateValue"null// string 状态值,状态唯一编码,同一个状态机下 不可重复

        "stateDesc"null// string 状态描述

        "stateType"null// integer 状态类型:1常规状态,2选择状态

        "smId"null// long 状态机id

    }],

    "smTransitions": [{

        "transitionId"null// long 流转id,保存时需要,新增时为空

        "transitionDesc"null// string 流转描述:便于标识流转,存在事件的时候建议跟事件描述一致

        "smId"null// long 状态机id

        "eventValue"null// string 事件值(code)

        "eventDesc"null// string 事件描述

        "eventRole"null// integer 事件角色,多个角色可以使用逗号隔开:1卖家(商家),2买家(用户)

        "showCondition"null// string 事件是否显示mvel条件

        "sourceState"null// string 源状态值

        "targetState"null// string 目标状态值

        "caseCondition"null// string 分支mvel条件(源状态为虚拟状态时有效)

        "caseOrder"null// integer 分支顺序

        "caseDefault"null// integer 是否默认分支:1是,2否

        "guardCondition"null// string 约束条件

        "transitionAction"null// string 回调业务系统对应接口http地址

    }]

}

基本的状态机中插入规则引擎的方式来实现分叉场景,备选方案有Drools、Easy Rules、RuleBook。

名称是否开源stars/forkslast_modified复杂度github地址
Drools1393/13412018/4/24高,配置规则的时候需要新增指定格式文档https://github.com/kiegroup/drools
Easy Rules770/2172018/4/20低,支持字符串创建规则,支持表达式语言https://github.com/j-easy/easy-rules
RuleBook217/412018/4/21低,支持Lambda表达式,https://github.com/rulebook-rules/rulebook

其中Easy Rules复杂度低,而且提供了MVEL的方式支持字符串的配置,鉴于此,对于相对简单而且需要UI页面的配置方式的场景来说,Easy Rules是最合适的选择,另外对应开源代码的显示,还可以很方便地扩展成支持其他EL表达式语言,如上面提到的Spring EL。

结合租房平台的具体流程,我们可以设计如下的订单状态机: ```markdown +-------------------------+ | Order States | +-------------------------+ | 新建 (New) | | 接收线索 (Lead Received) | | 需求确认 (Quote Request) | | 匹配房源 (Matching) | | 提供报价 (Quote Proposed)| | 审核中 (Approval Pending)| | 报价接受/拒绝 (Accepted/Rejected)| | 支付定金 (Deposit Paid) | | 预发提成 (Commission Pending)| | 审核通过 (Approved) | | 供应商通知 (Vendor Notified)| | 进行预订 (Booking Made) | | 退订/退款申请 (Refund Requested)| | 入住前退订/退款中 (Refund in Progress)| | 入住/违约 (Occupancy/Default)| | 结算完成 (Paid Out) | | 已完成 (Closed) | +-------------------------+ ``` 下面是简要描述每个状态之间的转换规则: - **新建**: 客户首次接触或SDR获取新线索。 - **接收线索**: SDR初步了解客户需求。 - **需求确认**: SDR协助确认客户需求并开始搜索房源。 - **匹配房源**: 顾问找到合适房源,向客户推荐。 - **提供报价**: 顾问为客户提供初步租金和条款。 - **审核中**: 学生或供应商查看并考虑报价。 - **报价接受/拒绝**: 学生同意或拒绝报价,决定订单。 - **支付定金**: 学生付款,订单进入预发提成状态。 - **预发提成**: 顾问确认收入,部分提成开始计算。 - **审核通过**: 供应商批准,订单准备进行下一步。 - **供应商通知**: 供应商告知相关人员订单详情。 - **进行预订**: 学生提交正式申请,开始租赁流程。 - **退订/退款申请**: 当订单遇到取消,客户提出退款。 - **退订/退款中**: 正在处理退款事宜,状态可能会多次切换。 - **入住/违约**: 根据入住或违约情况调整状态。 - **结算完成**: 财务确认收款后,订单关闭。 - **已完成**: 整个过程结束后,订单结束。 在这个状态机中,关键路径是从“匹配房源”到“预发提成”,而涉及退款的状态需要额外关注和及时处理,以维护良好的用户体验和公司收益。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值