通过状态机优化民宿订单系统

简介: 本文针对民宿业务下订单系统状态管理提出了一种解决方案:通过有限状态机简化订单状态的迁移处理,同时使订单状态变得可控。际使用中根据需要还可以将复杂的拆分为多个子状态机,比如支付状态机和业务状态机。 注:此处的状态机指“有限状态机”

1 有限状态机的概念

有限状态机(英语:finite-state machine,缩写:FSM)又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型 摘自 - 维基百科

FSM(有限状态机)可以使用状态图(或状态转移图)来表示。此外可以使用多种类型的状态转移表。下面展示最常见的表示:当前状态(B)和条件(Y)的组合指示出下一个状态(C)。完整的动作信息可以只使用脚注来增加。包括完整动作信息的FSM定义可以使用状态表

| 当前状态→ 条件↓ | 状态A | 状态B | 状态C |
| 条件X | ... | ... | ... |
| 条件Y | ... | 状态C | ... |
| 条件Z | .. . | ... | ... |

2 民宿业务背景

民宿作为新兴的一种住宿业态与酒店的预定机制不同,民宿的房东会根据房客的基本情况决定是否允许房客入住,即房东要确认房客的订单才能成交。

民宿订单系统作为中间平台既要支撑房源售卖方对自营房源的售卖又要支持对供应商房源的售卖;又要同时作为房源提供商将房源进行分销。

另外,为了考虑房客感受,订单系统要支付1)先支付后确认;2) 先确认后支付两种下单模式。

在复杂的业务背景下导致订单的状态比较多且状态的流转复杂,订单状态变化的触发点非常多。

3 民宿业务下的订单状态

由于考虑到之后民宿业务的扩展(比如可能接入保险等业务),订单设计时采用订单项的方式。OrderHeader表示订单头信息,每个业务存储在OrderItem中作为订单项存在。

针对民宿的业务场景设计出订单的状态如下:

主订单(OrderHeader)状态枚举

  • 处理中
  • 成功
  • 失败
  • 订单取消
  • 订单部分取消
  • 订单完成
  • 订单关闭

房源业务子订单(SpaceOrderItem)枚举
房源订单状态 可以拆分为支付线和业务线来看,前半部分代表支付状态,后半部分代表业务状态。支付状态和业务状态的枚举做笛卡尔积是逻辑上可能存在的所有状态列表。实际中只有下面的状态才是合法状态。

  1. 待支付待下单
  • 待支付下单失败
  • 待支付待确认
  • 待支付已确认
  • 待支付确认失败(拒单)
  • 待支付确认失败(超时)
  • 待支付已退订
  • 已支付待下单
  • 已支付待确认
  • 已支付已确认
  • 待退款下单失败
  • 待退款确认失败(拒单)
  • 待退款确认失败(超时)
  • 待退款已退订
  • 待退款部分退订
  • 部分退款部分退订
  • 部分退款已确认
  • 已退款下单失败
  • 已退款确认失败(拒单)
  • 已退款确认失败(超时)
  • 已退款已退订

订单状态的触发场景枚举. 下面的枚举场景是经过抽象的,实际业务场景中远远多于下面的7种

  1. 创建订单
  • 订单支付成功
  • 订单退款成功
  • 订单被主动拒绝
  • 订单被主动接受
  • 订单确认超时
  • 订单被主动取消

订单状态被触发时除了上面枚举的触发场景,还要结合当时订单的具体形态,比如是否为分销订单、是否为询单模式等综合判断。影响订单状态判断的条件枚举如下:

  1. 是否已经支付
  • 是否为分销订单
  • 是否为自营订单
  • 是否为询单模式

4 使用FSM对状态进行优化

考虑到上面枚举的各种订单状态类型以及复杂的订单状态变迁触发节点(上面枚举了7种,实际业务场景中要多得多),如果将订单状态的变化分步到具体每个触发的事件中会导致订单状态变化的不可控且极易导致状态变化的混乱。
此外,状态的迁移变化,请自行补脑 if... else ...

4.1 民宿订单状态转移表(部分)

状态迁移图.jpg

4.2 Java 实现民宿订单FSM(部分,仅做说明使用)

OrderFSM类

封装状态机的三个要素1)状态 2)事件 3)动作

/**
 * 订单简明状态机
 *
 * @author <a href="dongjianxing@aliyun.com">jeff</a>
 * @version 2017/1/22 13:37
 */
public class OrderFSM {
    private SpaceOrderFSMState fsmSpaceState = SpaceOrderFSMState.NOPAY_NOORDER;

    private OrderFSMContextData contextData;

    public static OrderFSM init(OrderFSMContextData contextData) {
        return new OrderFSM(contextData);
    }

    public OrderFSM(OrderFSMContextData contextData) {
        this.contextData = contextData;
    }

    public OrderFSM fire(FSMEvent event) throws TongaException {
        OrderFSM fsm = null;

        switch (event) {
            case ORDER_CREATE:
                fsm = orderCreate(contextData);
                break;
            ...略...
            default:
                throw new TongaException("订单FSM不支持的事件类型");
        }
        return fsm;
     }

     public SpaceOrderFSMState getFsmSpaceState() {
        return fsmSpaceState;
     }
     public enum SpaceOrderFSMState {

        NOPAY_NOORDER(1020, "待支付待下单"),
        NOPAY_ORDERFAILED(1023, "待支付下单失败"),
        NOPAY_NOCONFIRM(1010, "待支付待确认"),
        ... 略...
     }
     public enum FSMEvent {

        ORDER_CREATE, //订单创建
        BUSINOTIFY_ORDERFAILED,//业务结果通知,下单失败
        ... 略...
     }
     //以订单创建为例
     private OrderFSM orderCreate(OrderFSMContextData contextData) throws TongaException {
        if (fsmSpaceState != SpaceOrderFSMState.NOPAY_NOORDER) {
            throw new TongaException(ResultCodeEnum.OTHER_ERROR, "FSM:当前状态不允许 ORDER_CREATE 事件");
        }
        //分销
        if (contextData.isDistribute()) {
            if (contextData.isPayed()) {
                this.fsmSpaceState = contextData.isSelfSupport() ? SpaceOrderFSMState.PAYED_NOCONFIRM : SpaceOrderFSMState.PAYED_NOORDER;
            } else {
                this.fsmSpaceState = contextData.isSelfSupport() ? SpaceOrderFSMState.NOPAY_NOCONFIRM : SpaceOrderFSMState.NOPAY_NOORDER;
            }
        } else {
            //非分销
            this.fsmSpaceState = contextData.isSelfSupport() ? SpaceOrderFSMState.NOPAY_NOCONFIRM : SpaceOrderFSMState.NOPAY_NOORDER;
        }
        return this;
    }
 ... 略...
}

OrderFSMContextData存储状态机的上下文信息

用于具体状态变迁时的逻辑判断

 /**
 * 订单简明状态机上下文数据
 *
 * @author <a href="dongjianxing@aliyun.com">jeff</a>
 * @version 2017/1/22 13:40
 */
public class OrderFSMContextData {
    private boolean isPayed;//是否已经支付成功
    private boolean isDistribute;//是否为分销
    private boolean isSelfSupport;//是否自营
    private boolean isInquiry;//是否询单

    public OrderFSMContextData(boolean isPayed, boolean isDistribute, boolean isSelfSupport, boolean isInquiry) {
        this.isPayed = isPayed;
        this.isDistribute = isDistribute;
        this.isSelfSupport = isSelfSupport;
        this.isInquiry = isInquiry;
    }

    public boolean isPayed() {
        return isPayed;
    }

    public boolean isDistribute() {
        return isDistribute;
    }

    public boolean isSelfSupport() {
        return isSelfSupport;
    }

    public boolean isInquiry() {
        return isInquiry;
    }
}

订单状态机使用

OrderFSM fsm = OrderFSM.init(
new OrderFSMContextData(支付成功?,
                        分销订单?,
                        自营产品?,
                       询单模式?
)).fire(OrderFSM.FSMEvent.ORDER_CREATE);

关于作者
Java菜鸟。联系方式djx_19881022@163.com or dongjianxing@aliyun.com

目录
相关文章
|
6月前
|
存储 数据库
订单系统的设计
订单系统的设计
|
6月前
|
消息中间件 缓存 监控
订单系统的优化
订单系统的优化
|
7月前
|
安全
dapp预约抢单排单互助系统开发逻辑详细/功能说明/案例分析/方案规则/源码出售
Allow users to register accounts and verify their identities to ensure that the identities of participants are valid and authentic.
|
消息中间件 设计模式 移动开发
高德打车通用可编排订单状态机引擎设计
订单状态流转是交易系统的最为核心的工作,订单系统往往都会存在状态多、链路长、逻辑复杂的特点,还存在多场景、多类型、多业务维度等业务特性。在保证订单状态流转稳定性的前提下、可扩展性和可维护性是我们需要重点关注和解决的问题。
高德打车通用可编排订单状态机引擎设计
|
26天前
|
供应链 数据库 UED
商城如何设计订单系统超级有用
商城如何设计订单系统超级有用
32 0
|
1月前
|
新零售 小程序 搜索推荐
排队免单模式小程序商城系统开发方案
新零售不再将线上和线下视为两个独立的销售渠道,而是将其整合为一个完整的销售生态系统
|
6月前
|
存储 安全 前端开发
DApp公排互助预约抢单排单模式系统开发参考版/详细流程/方案逻辑/规则玩法/案例设计/源码程序
需求分析:与团队明确系统的需求、目标和范围,包括公排互助预约抢单排单模式系统的功能、规则、奖励机制等方面
|
7月前
|
存储 运维 区块链
|
9月前
|
存储 分布式数据库 区块链
DAPP竞拍互助拆分公排系统开发玩法规则/详细逻辑/源码程序
  区块链技术一般用于构建交易系统,而且要保证交易的信息真实可信,可追踪且不可篡改。每一次交易的信息被确认后存储在一个区块中,区块信息通过散列技术加密,以保证信息不被篡改。这些区块按时间顺序构成链条。每个节点都保有完整的区块链信息,个别节点的信息损坏,不会对区块链信息产生影响。这种信息记录方式被称作分布式账本。
|
11月前
|
数据挖掘 网络架构
短链系统设计-服务设计
该系统其实很简单,只需要有一个 service即可:URL Service。由于 tiny url只有一个 UrlService: 本身其实就是个小的独立应用 也无需关心其他任何业务功能
110 0
短链系统设计-服务设计