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

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

作者: 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