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

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

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月前
|
消息中间件 缓存 监控
订单系统的优化
订单系统的优化
|
6月前
|
存储 区块链 数据安全/隐私保护
DApp互助预约排单系统开发设计规则逻辑解析
DApp互助预约排单系统开发设计规则逻辑解析
|
消息中间件 设计模式 移动开发
高德打车通用可编排订单状态机引擎设计
订单状态流转是交易系统的最为核心的工作,订单系统往往都会存在状态多、链路长、逻辑复杂的特点,还存在多场景、多类型、多业务维度等业务特性。在保证订单状态流转稳定性的前提下、可扩展性和可维护性是我们需要重点关注和解决的问题。
高德打车通用可编排订单状态机引擎设计
|
22天前
|
供应链 数据库 UED
商城如何设计订单系统超级有用
商城如何设计订单系统超级有用
29 0
|
7月前
|
安全
dapp互助预约排单抢单项目系统开发规则玩法/逻辑说明/案例介绍/方案设计/源码程序
The development of DApp appointment and scheduling mutual assistance system refers to the development of a mutual assistance system based on blockchain technology and decentralized application programs (DApp). This system is usually designed as a mutual aid or sharing economy model, aimed at providi
|
6月前
|
存储 前端开发 安全
dapp矩阵公排互助预约排单抢单项目系统开发指南流程丨案例设计丨功能逻辑丨规则玩法丨项目方案丨源码程序
需求分析:与团队明确系统的需求和目标,包括公排互助预约排单抢单项目系统的功能、规则、奖励机制等方面。
|
7月前
|
存储 安全 前端开发
预约上门按摩项目系统开发详细流程/案例介绍/功能逻辑/需求方案/源码模式
确定系统的目标用户,例如个人用户或企业用户。 - 确定系统的核心功能,如用户注册和登录、服务列表和预约管理、支付和评价反馈等。 - 确定技术平台和开发语言,如Web应用还是移动应用,以及开发语言和框架的选择。 - 制定项目计划,并确定开发阶段和时间安排。
|
7月前
|
安全
上门按摩预约系统开发方案项目/案例详细/需求逻辑/流程设计/源码功能
Implement a user authentication mechanism to ensure the authenticity and security of user identities.
|
存储 监控 供应链
聊聊「订单」业务的设计与实现
订单业务一直都是系统研发中的核心模块,订单的产生过程,与系统中的很多模块都会高度关联,比如账户体系、支付中心、运营管理等,即便单看订单本身,也足够的复杂;
11241 3
聊聊「订单」业务的设计与实现