如何处理多条件订单状态的变化方式?

qjdice
  • 9

在一个点餐系统中,有着外卖单,堂食单等。对应不同的订单与不同的动作和设置会有不同的状态变化,在代码中if elseif要写30-40多行,对于这种情况是否有更好的处理方法?

举例如下:
判断项:商家开启先食后付 是否自动接单 是否有打印机 打印是否成功 是否自动清台
动作: 下单 接单 拒单 顾客取消单 顾客支付 清台 结账
状态: 待确认 待处理 拒绝 完成 取消 进行中 超时 申请退款

如上由5种判断项 组合出多种变化 在每种变化中 不同的动作 改变订单不同的状态,像这种状态模型,除了无数的 if elseif 是否有更好的方法实现?

想要实现:输入动作 输出状态

想要一个思路,非常感谢!

回复
阅读 2.5k
4 个回答
helloworld_
  • 3k
✓ 已被采纳

给一个大概思路吧。java实现。可以稍微参考下。



package com.ui;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class OrderStatusService {
    
    /**
     * 映射关系列表
     */
    public  static List<OrderStatusMapper> mapperList = new ArrayList<OrderStatusMapper>();
    
    static {
        /**
         * 初始化判断项、订单动作到状态的映射,这里只为演示,实际中映射关系最好保存在配置文件中或者数据库中,一般在应用启动的时候,从配置文件或者数据库加载,保存一份即可。
         * 
         */
        OrderStatusMapper m1 = new OrderStatusMapper();
        m1.addJudgementItems(1,2,4,6) //先吃后付 and 自动接单 and 有打印机 and 打印成功
        .addAction2statusItem(1,6)//下单动作:进行中 
        .addAction2statusItem(7, 4); //结账动作:已完成
        
        OrderStatusMapper m2 = new OrderStatusMapper();
        m2.addJudgementItems(3,5) 
        .addAction2statusItem(2,1)
        .addAction2statusItem(4, 3); 
        
        mapperList.add(m1);
        mapperList.add(m2);
        
    }
    
    /**
     * 是否是相等的set
     * @param source 
     * @param dest
     * @return
     */
    public boolean  isEqualSet(Set<Integer> source,Set<Integer> dest){
        if(null == source || null == dest){
            return false;
        }
        if(source.size() != dest.size()){
            return false;
        }
        for(Iterator<Integer> it = source.iterator();it.hasNext();){
            if(!dest.contains(it.next())){
                return false;
            }
        }
        return true;
    }
    public static void main(String[] args) {
        Order order = new Order();
        order.setOrderAction(1);//下单
        order.setJudgementItems(new HashSet<Integer>(Arrays.asList(1,2,4,6)));//先吃后付 and 自动接单 and 有打印机 and 打印成功
        //获取订单下一个状态
        System.out.println(new OrderStatusService().getNextOrderStatus(order));//  结果为 6(进行中)
    }
    /**
     * 获取下一个订单状态
     * @param curOrder
     * @return
     */
    public Integer getNextOrderStatus(Order curOrder){
        for(OrderStatusMapper mapper : mapperList){
            if(isEqualSet(curOrder.getJudgementItems(), mapper.getJudgementItems()) &&  null != curOrder.getOrderAction()){
                return mapper.getAction2statusMap().get(curOrder.getOrderAction());
            }
        }
        return null;
    }
    
}

/**
 * 订单类型,订单动作到状态的映射。
 *
 */
class OrderStatusMapper{
    
    /**
     * 判断项
     */
    private Set<Integer> judgementItems = new HashSet<Integer>();
    
    /**
     * 订单动作到状态关系
     */
    private Map<Integer,Integer> action2statusMap = new HashMap<Integer,Integer>();
    
    /**
     * 下一个订单状态
     */
    private Integer nextStatus;


    public Set<Integer> getJudgementItems() {
        return judgementItems;
    }

    public OrderStatusMapper addJudgementItems(Integer ...items) {
        if(null == items || items.length <= 0){
            return this;
        }
        for(Integer cur : items){
            this.judgementItems.add(cur);
        }
        return this;
    }

   

    public Map<Integer, Integer> getAction2statusMap() {
        return action2statusMap;
    }

    public OrderStatusMapper addAction2statusItem(Integer action,Integer status) {
        if(null == action || null == status){
            return this;
        }
        this.action2statusMap.put(action, status);
        return this;
    }

    public Integer getNextStatus() {
        return nextStatus;
    }

    public OrderStatusMapper setNextStatus(Integer nextStatus) {
        this.nextStatus = nextStatus;
        return this;
    }
}


class Order{
    /**
     * 判断项目
     * 1:商家开启先食后付 ;
     * 2:自动接单;
     * 3:不自动接单
     * 4:有打印机
     * 5:没有打印机
     * 6:打印成功
     * 7:打印不成功
     * 8:自动清台
     * 9:不自动清台
     */
    private Set<Integer> judgementItems;
    
    /**
     * 订单动作
     * 1:下单 
     * 2:接单 
     * 3:拒单 
     * 4:顾客取消单
     * 5:顾客支付 
     * 6:清台
     * 7:结账
     */
    private Integer orderAction;
    
    /**
     * 订单状态
     * 1:待确认 
     * 2:待处理 
     * 3:拒绝 
     * 4:完成 
     * 5:取消 
     * 6:进行中 
     * 7:超时 
     * 8:申请退款
     */
    private Integer orderStatus;

    
    public Set<Integer> getJudgementItems() {
        return judgementItems;
    }

    public void setJudgementItems(Set<Integer> judgementItems) {
        this.judgementItems = judgementItems;
    }

    public Integer getOrderAction() {
        return orderAction;
    }

    public void setOrderAction(Integer orderAction) {
        this.orderAction = orderAction;
    }

    public Integer getOrderStatus() {
        return orderStatus;
    }

    public void setOrderStatus(Integer orderStatus) {
        this.orderStatus = orderStatus;
    }
}
 
Gota
  • 3
新手上路,请多包涵

试试看位运算可不可以, 每个比特位表示一个条件的状态.
比如当前状态为: 0111
某个动作的执行条件为: 0100 即只要第二个状态位为真的时候执行
运算的时候就判断 0111 & 0100 == 0100 就可以判断这个动作要不要执行了
这样每个动作对应一个 if, 会比原来少一点, 但是状态转换的代码可能会多一点, 这个就看楼主权衡了

dodopy
  • 2.4k

状态切换和流程控制可以使用有限状态机定义与处理,相关开源的库也比较丰富。

将每种状态使用0,1标识。然后组合成一个状态码(string),如:01001.
定义一个数组来存储这个状态码,如 let code = [0,1,0,1,0];
声明一个object(或者Map or Set)来存状态码和对应需要执行的函数,如:

let status = {
    '01000': function1,
    '01010': function2,
    ...
}

使用时: status[code.join('')]()。

宣传栏