美文网首页
设计模式-状态模式(行为型)

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

作者: NealLemon | 来源:发表于2019-09-19 12:11 被阅读0次

定义

  • 允许一个对象在其内部状态改变时,改变它的行为。
  • 一个对象当他的内部状态改变时,也需要改变他的行为,当然只做状态的互相转换也可以。
  • 当控制一个对象状态转变比较复杂的时候,把状态的判断逻辑转移到表示不同状态的一系列类当中。

适用场景

  • 一个对象存在多个状态(不同状态下行为不同),且状态可以相互转换。

优点

  • 将不同的状态隔离。
  • 把各种状态的转换逻辑,分布到State的子类中,减少相互间的依赖。
  • 增加新的状态非常简单。

缺点

  • 面多业务复杂的场景,导致类数目的增加,系统变复杂。

代码

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

  • 待付款状态
  • 付款状态
  • 等待发货
  • 发货状态
  • 收货状态

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

购物状态抽象类(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

给出了已经付款的提示。

小结

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

相关文章

网友评论

      本文标题:设计模式-状态模式(行为型)

      本文链接:https://www.haomeiwen.com/subject/uexxyctx.html