设计模式-状态模式(行为型)

2019-09-19  本文已影响0人  NealLemon

定义

适用场景

优点

缺点

代码

我们在购物的时候,通常会有这么几个状态

接下来,让我们用代码简单实现一下这个状态转换的过程。

购物状态抽象类(ShoppingState)

public abstract class ShoppingState {
    protected ShoppingContext shoppingContext;

    public void setShoppingContext(ShoppingContext shoppingContext) {
        this.shoppingContext = shoppingContext;
    }

    //等待付款
    public abstract void waitingPay();
    //付款
    public abstract void pay();
    //等待发货
    public abstract void waitingDelivery();
    //发货
    public abstract void delivery();
    //收货
    public abstract void receive();
}

抽象类中 除了上述的几个状态方法之外,还有一个 购物上下文(ShoppingContext),这个就是管理整个状态转换的容器。

购物上下文(ShoppingContext)

public class ShoppingContext {

    private ShoppingState shoppingState;

    public final static WaitingPayState WAITING_PAY_STATE = new WaitingPayState();

    public final static PayState PAY_STATE = new PayState();

    public final static WaitingDeliveryState WAITING_DELIVERY_STATE = new WaitingDeliveryState();

    public final static DeliveryState DELIVERY_STATE = new DeliveryState();

    public final static ReceiveState RECEIVE_STATE = new ReceiveState();


    public ShoppingState getShoppingState() {
        return shoppingState;
    }


    public void setShoppingState(ShoppingState shoppingState) {
        this.shoppingState = shoppingState;
        this.shoppingState.setShoppingContext(this);
    }


    public void waitingPay() {
        this.shoppingState.waitingPay();
    }


    public void pay() {
        this.shoppingState.pay();
    }


    public void waitingDelivery() {
        this.shoppingState.waitingPay();
    }


    public void delivery() {
        this.shoppingState.delivery();
    }

    public void receive() {
        this.shoppingState.receive();
    }
}

购物上下文类中 包含了整个购物流程的实现方法,同时提供了切换上下文状态的方法(setShoppingStatesetShoppingState(ShoppingState shoppingState))

具体状态实现类

待付款状态(WaitingPayState

public class WaitingPayState extends ShoppingState {
    @Override
    public void waitingPay() {
        System.out.println("等待付款状态.....");
    }

    @Override
    public void pay() {
        System.out.println("可以进行付款.....");
        super.shoppingContext.setShoppingState(ShoppingContext.PAY_STATE);
    }

    @Override
    public void waitingDelivery() {
        System.out.println("请先付款.....");
    }

    @Override
    public void delivery() {
        System.out.println("请先付款.....");
    }

    @Override
    public void receive() {
        System.out.println("请先付款.....");
    }
}

这里由于待付款状态只能切换到支付状态,因此在WaitingPayState这个类中的pay()方法中,我们进行了上下文状态切换,其他的方法只能给出提示,必须先进行付款。

以下几个实现类也是如此的逻辑,就不重复解释了。

付款状态(PayState)

public class PayState extends ShoppingState {
    @Override
    public void waitingPay() {
        System.out.println("已经付款了.....");
    }

    @Override
    public void pay() {
        System.out.println("付款状态.....");
    }

    @Override
    public void waitingDelivery() {
        System.out.println("等待发货.....");
        super.shoppingContext.setShoppingState(ShoppingContext.WAITING_DELIVERY_STATE);
    }

    @Override
    public void delivery() {
        System.out.println("等待发货.....");
    }

    @Override
    public void receive() {
        System.out.println("等待发货.....");
    }
}

等待发货状态(WaitingDeliveryState)

public class WaitingDeliveryState extends ShoppingState{
    @Override
    public void waitingPay() {
        System.out.println("已经付款.....");
    }

    @Override
    public void pay() {
        System.out.println("已经付款.....");
    }

    @Override
    public void waitingDelivery() {
        System.out.println("等待发货状态.....");
    }

    @Override
    public void delivery() {
        System.out.println("可以发货.....");
        super.shoppingContext.setShoppingState(ShoppingContext.DELIVERY_STATE);
    }

    @Override
    public void receive() {
        System.out.println("等待发货.....");
    }
}

发货状态(DeliveryState)

public class DeliveryState extends ShoppingState{
    @Override
    public void waitingPay() {
        System.out.println("已经付款.....");
    }

    @Override
    public void pay() {
        System.out.println("已经付款.....");
    }

    @Override
    public void waitingDelivery() {
        System.out.println("已经发货.....");
    }

    @Override
    public void delivery() {
        System.out.println("发货状态.....");
    }

    @Override
    public void receive() {
        System.out.println("等待确认收货.....");
        super.shoppingContext.setShoppingState(ShoppingContext.RECEIVE_STATE);
    }
}

收货状态(ReceiveState)

public class ReceiveState extends ShoppingState {
    @Override
    public void waitingPay() {
        System.out.println("已经付款.....");
    }

    @Override
    public void pay() {
        System.out.println("已经付款.....");
    }

    @Override
    public void waitingDelivery() {
        super.shoppingContext.setShoppingState(ShoppingContext.WAITING_DELIVERY_STATE);
    }

    @Override
    public void delivery() {
        super.shoppingContext.setShoppingState(ShoppingContext.DELIVERY_STATE);
    }

    @Override
    public void receive() {
        System.out.println("等待收货状态.....");
    }
}

UML类图

stateUML.jpg

我们可以看到在上下文中,组合了所有状态,通过上下,可以进行状态切换。

测试代码

public class StateBootStrap {

    public static void main(String[] args) {
        ShoppingContext shoppingContext = new ShoppingContext();
        shoppingContext.setShoppingState(ShoppingContext.WAITING_PAY_STATE);
        shoppingContext.waitingDelivery();
        System.out.println("当前状态:"+shoppingContext.getShoppingState().getClass().getSimpleName());

        //进行付款
        shoppingContext.pay();
        System.out.println("当前状态:"+shoppingContext.getShoppingState().getClass().getSimpleName());

        //等待发货
        shoppingContext.waitingDelivery();
        System.out.println("当前状态:"+shoppingContext.getShoppingState().getClass().getSimpleName());

        //发货
        shoppingContext.delivery();
        System.out.println("当前状态:"+shoppingContext.getShoppingState().getClass().getSimpleName());

        //收货
        shoppingContext.receive();
        System.out.println("当前状态:"+shoppingContext.getShoppingState().getClass().getSimpleName());
    }
}

测试结果

stateResult.jpg

在这里我们可以做一个小改动,当我们在收货状态的时候,再次付款时,会发生什么样的输出呢,我们在上面代码中添加一段代码

shoppingContext.pay();

我们来看一下结果

stateResult1.jpg

给出了已经付款的提示。

小结

因为状态模式大部分是在业务场景中使用的,因此开源框架中,极少有相关的实现,希望大家结合实际业务去选择合适的设计模式。不要重度设计。

上一篇下一篇

猜你喜欢

热点阅读