状态模式处理订单

zhy

发布于 2020.03.11 20:03 阅读 2373 评论 0

问题场景:

    对于一个订单在不同的阶段有不同的状态,不同的状态处理逻辑也不一样。如果使用if/esle来判断订单状态,从而实现不同的操作。这样难以应对变化,增加一个状态,我们就需要增加一个分之,还可能影响原有逻辑判断。

 

if(待支付){

xxx

}else if(已付款){

xxxx

}else if(代发货){

xxxx

}else if(已发货){

xxxx

}

......

 

    状态模式的主要目的是: 当控制一个对象状态转换的条件表达式过于复杂时,把相关“判断逻辑”提取出来,放到一系列的状态类当中,这样可以把原来复杂的逻辑判断简单化。

    比如上述订单的各种状态:待付款,已付款,待发货,已发货,已签收等,接下来对其进行实现:

 

/**
 * 订单类
 */
public class OrderContext {
    private State state;

    //初始化订单的时候状态设置待付款
    public OrderContext(String userName) {
        System.out.println("用户 " + userName +" 下单");
        this.state = new ToBePayState();
    }

    /**
     * 进行下一个状态(例如待付款-->付款)
     */
    public void doNext(){
        state.doNext(this);
    }

    public State getState() {
        return state;
    }

    public void setState(State state) {
        this.state = state;
    }
}

 

/**
 * 订单状态
 */
public interface State {
    void doNext(OrderContext orderContext);
}

/**
 * 待付款状态
 */
public class ToBePayState implements State{
    @Override
    public void doNext(OrderContext orderContext) {
        System.out.println("付款成功!");
        orderContext.setState(new PaidState());
    }
}

/**
 * 付款状态
 */
public class PaidState implements State{
    @Override
    public void doNext(OrderContext orderContext) {
        System.out.println("运送中!");
        orderContext.setState(new DeliverGoodsState());
    }
}

/**
 * 运送状态
 */
public class DeliverGoodsState implements State {
    @Override
    public void doNext(OrderContext orderContext) {
        System.out.println("待签收!");
        orderContext.setState(new GoodsToBeReceivedState());
    }
}

/**
 * 待签收状态
 */
public class GoodsToBeReceivedState implements State{
    @Override
    public void doNext(OrderContext orderContext) {
        System.out.println("已签收!");
        orderContext.setState(new GoodsReceivedState());
    }
}

/**
 * 已签收状态
 */
public class GoodsReceivedState implements State{
    @Override
    public void doNext(OrderContext orderContext) {
        System.out.println("确认收货!");
        orderContext.setState(new SuccessState());
    }
}

/**
 * 确认收货状态
 */
public class SuccessState implements State{
    @Override
    public void doNext(OrderContext orderContext) {
        System.out.println("交易已完成,没有下一步了!");
    }
}

    public static void main(String[] args) {
        OrderContext orderContext = new OrderContext("张三");
        orderContext.doNext();
        orderContext.doNext();
        orderContext.doNext();
        orderContext.doNext();
        orderContext.doNext();
        orderContext.doNext();
    }

 

运行结果:

 

     使用状态模式代码可以封装状态的转换规则,在状态模式中可以将状态的行为(转化)代码封装在具体状态类中,可以对状态转换代码进行集中管理,方便维护

    状态模式对“开闭原则”的支持并不太好,增加新的状态类需要修改那些负责状态转换的源代码,否则无法转换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。