状态模式

Posted internetjava

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了状态模式相关的知识,希望对你有一定的参考价值。

最近发现项目中的判断太多,大量的if-else结构,想着重构下,于是接触到了状态模式。
这种设计模式就是java多态的体现,没有想象的那么神奇。

状态模式:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

1、有一个对象,它是有状态的。
2、这个对象在状态不同的时候,行为不一样。
3、这些状态是可以切换的,而非毫无关系。

技术图片

 

 

图中包含三个角色。
Context:它就是那个含有状态的对象,它可以处理一些请求,这些请求最终产生的响应会与状态相关。
State:状态接口,它定义了每一个状态的行为集合,这些行为会在Context中得以使用。
ConcreteState:具体状态,实现相关行为的具体状态类。
其他解释
环境(Context)角色,也成上下文:定义客户端所感兴趣的接口,并且保留一个具体状态类的实例。这个具体状态类的实例给出此环境对象的现有状态。
抽象状态(State)角色:定义一个接口,用以封装环境(Context)对象的一个特定的状态所对应的行为。
具体状态(ConcreteState)角色:每一个具体状态类都实现了环境(Context)的一个状态所对应的行为。

个人还是喜欢把环境角色context带入接口的方法参数中,这样逻辑更清楚;
另外的方式是把context放入各个具体状态角色的构造方法中,当实例化context的时候,通过具体状态的构造方法加载此context实例到具体状态角色中

举例一
本例子模拟购物的整个过程,包括下单,付款,收货,评价,退款,结束等。

状态接口

public interface Event {
    //下单
    void order(Shopping shopping,Boolean isConfirm) ;
    //付款
    void pay(Shopping shopping,Boolean isConfirm);
    //签收
    void receive(Shopping shopping,Boolean isConfirm);
    //评价
    void evaluate(Shopping shopping,Boolean isConfirm);
    //订单结束
    void finish(Shopping shopping,Boolean isConfirm);
    //退款
    void refund(Shopping shopping,Boolean isConfirm);
}

 

抽象类主要处理异常的情况,即用户重复提交某个状态时出现

public  class AbstractEvent implements Event {
    @Override
    public void order(Shopping shopping, Boolean isConfirm) {
        System.out.println("亲亲,下单异常");
    }

    @Override
    public void pay(Shopping shopping, Boolean isConfirm) {
        System.out.println("亲亲,支付异常");
    }

    @Override
    public void receive(Shopping shopping, Boolean isConfirm) {
        System.out.println("亲亲,接收异常");
    }

    @Override
    public void evaluate(Shopping shopping, Boolean isConfirm) {
        System.out.println("亲亲,评价异常");
    }

    @Override
    public void finish(Shopping shopping, Boolean isConfirm) {
        System.out.println("亲亲,结束操作流程错误");
    }

    @Override
    public void refund(Shopping shopping, Boolean isConfirm) {
        System.out.println("您的订单已经退款,请不要重复提交");
    }
}

 

具体状态角色 - 下单

public class Order extends AbstractEvent {
    @Override
    public void order(Shopping shopping, Boolean isConfirm) {
        if(isConfirm){
            System.out.println("恭喜您,下单成功");
            shopping.setEvent(Shopping.PAY_STATE);//确定下单,进入支付页面
        }else {
            System.out.println("订单页面取消成功,回到主页面");
            shopping.setEvent(Shopping.REFUND);
        }
    }
}

 

具体状态角色 - 支付

public class Pay extends AbstractEvent {
    @Override
    public void pay(Shopping shopping, Boolean isConfirm) {
        if(isConfirm){
            System.out.println("恭喜您,支付成功");
            shopping.setEvent(Shopping.RECEIVE_STATE);//进入收货阶段
        }else {
            System.out.println("支付页面,取消订单成功");
            shopping.setEvent(Shopping.REFUND);
        }
    }
}

 

具体状态角色 - 接收

public class Receive extends AbstractEvent {
    @Override
    public void receive(Shopping shopping, Boolean isConfirm) {
        if(isConfirm){
            System.out.println("亲,签收物品成功,期待下次与您再次相见");
            shopping.setEvent(Shopping.EVALUATE_STATE);
        }else {
            System.out.println("亲,签收阶段退款成功");
            shopping.setEvent(Shopping.REFUND);
        }
    }
}

 

具体状态角色 - 评价

public class Evaluate extends AbstractEvent {
    @Override
    public void evaluate(Shopping shopping, Boolean isConfirm) {
        if(isConfirm){
            System.out.println("评价商品成功");
            shopping.setEvent(Shopping.FINISH_STATE);
        }else {
            System.out.println("评价阶段,退款成功");
            shopping.setEvent(Shopping.REFUND);
        }
    }
}

 

具体状态角色 - 完成

public class Finish extends AbstractEvent {
    @Override
    public void finish(Shopping shopping, Boolean isConfirm) {
        if(isConfirm){
            System.out.println("订单结束,感谢您的光临");
        }else {
            System.out.println("亲爱的客人,请您分享使用心得");
        }
    }
}

 

具体状态角色 - 退款

public class Refund extends AbstractEvent {
    @Override
    public void refund(Shopping shopping, Boolean isConfirm) {
        if(isConfirm){
            System.out.println("抱歉客官,给您带来不好的购物体验了,已为您退款,请见谅");
            shopping.setEvent(Shopping.FINISH_STATE);
        }
    }
}

 

环境角色,有状态的对象 - 购物对象

public class Shopping {
    public static final Event ORDER_STATE = new Order();
    public static final Event PAY_STATE = new Pay();
    public static final Event RECEIVE_STATE = new Receive();
    public static final Event EVALUATE_STATE = new Evaluate();
    public static final Event FINISH_STATE = new Finish();
    public static final Event REFUND = new Refund();
    //状态记录,默认进入下单状态
    private Event event = ORDER_STATE;

    public Event getEvent() {
        return event;
    }    
    public void setEvent(Event event) {
        this.event = event;
    }

    public void startOrder(Boolean isConfirm){
        event.order(this,isConfirm);
    }
    public void startPay(Boolean isConfirm){
        event.pay(this,isConfirm);
    }
    public void startReceive(Boolean isConfirm){
        event.receive(this,isConfirm);
    }
    public void startEvaluate(Boolean isConfirm){
        event.evaluate(this,isConfirm);
    }
    public void startFinish(Boolean isConfirm){
        event.finish(this,isConfirm);
    }
    public void startRefund(Boolean isConfirm){
        event.refund(this,isConfirm);
    }
}

 

客户启动段

public class Client {
    public static void main(String[] args) {
        Shopping shopping = new Shopping();
        //下单成功
        shopping.startOrder(true);
        shopping.startOrder(true);
        shopping.startOrder(true);
        shopping.startOrder(true);
        shopping.startOrder(true);
        shopping.startPay(true);
        shopping.startReceive(false);
        shopping.startRefund(true);
        shopping.startEvaluate(true);
        shopping.startFinish(true);
    }
}

 

运行结果:

技术图片

 

 

状态模式适用于某一个对象的行为取决于该对象的状态,并且该对象的状态会在运行时转换,又或者有很多的if else判断,而这些判断只是因为状态不同而不断的切换行为。

以上是关于状态模式的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段13——Vue的状态大管家

VSCode自定义代码片段13——Vue的状态大管家

方向/配置更改后如何维护 ListView 片段状态?

java BottomBarNavigation代码保留片段状态

为不同方向使用不同布局时,在方向更改时保存片段状态

多选模式列表视图行在删除后保持选中状态