设计模式(二十)状态模式

作者: 我犟不过你 | 来源:发表于2021-01-25 16:09 被阅读0次

    1、概述

    状态模式是一种行为设计模式, 让你能在一个对象的内部状态变化时改变其行为, 使其看上去就像改变了自身所属的类一样。

    2、使用场景

    1)如果对象需要根据自身当前状态进行不同行为, 同时状态的数量非常多且与状态相关的代码会频繁变更的话, 可使用状态模式。
    2)如果某个类需要根据成员变量的当前值改变自身行为, 从而需要使用大量的条件语句时, 可使用该模式。
    3)当相似状态和基于条件的状态机转换中存在许多重复代码时, 可使用状态模式。

    3、实例

    有如下场景:

    策划一场活动,活动有以下状态:
    编辑,保存,提交,审核通过、审核拒绝、关闭、开启
    

    其状态变化如下图所示:

    状态.png

    创建状态的顶层抽象:

    /**
     * 抽象状态类
     * @date: 2021/1/25
     * @author weirx
     * @version 3.0
     */
    abstract class State {
    
        public Activity activity;
    
        public State(Activity activity) {
            this.activity = activity;
        }
    
        /**
         * 编辑
         */
        public abstract State edit();
    
        /**
         * 保存
         */
        public abstract State save();
    
        /**
         * 提交
         */
        public abstract State submit();
    
        /**
         * 审核通过
         */
        public abstract State pass();
    
        /**
         * 审核拒绝
         */
        public abstract State reject();
    
        /**
         * 开启
         */
        public abstract State start();
    
        /**
         * 关闭
         */
        public abstract State close();
    
    }
    

    创建活动:

    /**
     * 活动
     * @date: 2021/1/25
     * @author weirx
     * @version 3.0
     */
    public class Activity {
    
        /**
         * 活动id
         */
        private String id;
    
        /**
         * 活动名称
         */
        private String name;
    
        /**
         * 更新状态
         */
        public State changeState(State state){
            return state;
        }
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Activity(String id, String name) {
            this.id = id;
            this.name = name;
        }
    }
    

    创建几种状态的具体类:

    package com.cloud.bssp.designpatterns.state;
    
    /**
     * 编辑状态
     * @date: 2021/1/25
     * @author weirx
     * @version 3.0
     */
    public class EditState extends State {
    
        public EditState(Activity activity) {
            super(activity);
        }
    
        @Override
        public State edit() {
            System.out.println("活动正在编辑");
            return this;
        }
    
        @Override
        public State save() {
            System.out.println("活动已保存");
            return activity.changeState(new SaveState(activity));
        }
    
        @Override
        public State submit() {
            System.out.println("活动已提交");
            return activity.changeState(new SubmitState(activity));
        }
    
        @Override
        public State pass() {
            System.out.println("编辑中无法审核");
            return this;
        }
    
        @Override
        public State reject() {
            System.out.println("编辑中无法审核");
            return this;
        }
    
        @Override
        public State start() {
            System.out.println("编辑中无法开启");
            return this;
        }
    
        @Override
        public State close() {
            System.out.println("编辑中无法关闭");
            return this;
        }
    }
    
    
    package com.cloud.bssp.designpatterns.state;
    
    /**
     * 保存状态
     * @date: 2021/1/25
     * @author weirx
     * @version 3.0
     */
    public class SaveState extends State{
    
        public SaveState(Activity activity) {
            super(activity);
        }
    
        @Override
        public State edit() {
            System.out.println("活动正在编辑中");
            return activity.changeState(new EditState(activity));
        }
    
        @Override
        public State save() {
            System.out.println("活动已保存");
            return this;
        }
    
        @Override
        public State submit() {
            System.out.println("活动已提交");
            return activity.changeState(new SubmitState(activity));
        }
    
        @Override
        public State pass() {
            System.out.println("保存状态无法审核");
            return this;
        }
    
        @Override
        public State reject() {
            System.out.println("保存状态无法审核");
            return this;
        }
    
        @Override
        public State start() {
            System.out.println("保存状态无法开启");
            return this;
        }
    
        @Override
        public State close() {
            System.out.println("保存状态无法关闭");
            return this;
        }
    }
    
    
    package com.cloud.bssp.designpatterns.state;
    
    /**
     * 提交状态
     * @date: 2021/1/25
     * @author weirx
     * @version 3.0
     */
    public class SubmitState extends State{
    
        public SubmitState(Activity activity) {
            super(activity);
        }
    
        @Override
        public State edit() {
            System.out.println("活动已提交,无法编辑");
            return this;
        }
    
        @Override
        public State save() {
            System.out.println("活动已提交,无法保存");
            return this;
        }
    
        @Override
        public State submit() {
            System.out.println("活动已提交,无法再次提交");
            return this;
        }
    
        @Override
        public State pass() {
            System.out.println("活动已经审核通过");
            return activity.changeState(new PassState(activity));
        }
    
        @Override
        public State reject() {
            System.out.println("活动已经审核拒绝");
            return activity.changeState(new RejectState(activity));
        }
    
        @Override
        public State start() {
            System.out.println("未审核无法开启");
            return this;
        }
    
        @Override
        public State close() {
            System.out.println("未审核无法关闭");
            return this;
        }
    }
    
    
    package com.cloud.bssp.designpatterns.state;
    
    /**
     * 通过状态
     * @date: 2021/1/25
     * @author weirx
     * @version 3.0
     */
    public class PassState extends State{
    
        public PassState(Activity activity) {
            super(activity);
        }
    
        @Override
        public State edit() {
            System.out.println("审核通过无法编辑");
            return this;
        }
    
        @Override
        public State save() {
            System.out.println("审核通过无法保存");
            return this;
        }
    
        @Override
        public State submit() {
            System.out.println("审核通过无法提交");
            return this;
        }
    
        @Override
        public State pass() {
            System.out.println("审核通过无法再次审核");
            return this;
        }
    
        @Override
        public State reject() {
            System.out.println("审核通过无法再次审核");
            return this;
        }
    
        @Override
        public State start() {
            System.out.println("活动已经开启");
            return activity.changeState(new StartState(activity));
        }
    
        @Override
        public State close() {
            System.out.println("审核通过无法关闭");
            return this;
        }
    }
    
    
    package com.cloud.bssp.designpatterns.state;
    
    /**
     * 拒绝状态
     * @date: 2021/1/25
     * @author weirx
     * @version 3.0
     */
    public class RejectState extends State{
    
        public RejectState(Activity activity) {
            super(activity);
        }
    
        @Override
        public State edit() {
            System.out.println("审核拒绝无法编辑");
            return this;
        }
    
        @Override
        public State save() {
            System.out.println("审核拒绝无法保存");
            return this;
        }
    
        @Override
        public State submit() {
            System.out.println("审核拒绝无法提交");
            return this;
        }
    
        @Override
        public State pass() {
            System.out.println("审核拒绝无法再次审核");
            return this;
        }
    
        @Override
        public State reject() {
            System.out.println("审核拒绝无法再次审核");
            return this;
        }
    
        @Override
        public State start() {
            System.out.println("审核拒绝无法开启");
            return this;
        }
    
        @Override
        public State close() {
            System.out.println("活动已经关闭");
            return activity.changeState(new StartState(activity));
        }
    }
    
    
    package com.cloud.bssp.designpatterns.state;
    
    /**
     * 开启状态
     * @date: 2021/1/25
     * @author weirx
     * @version 3.0
     */
    public class StartState extends State{
    
        public StartState(Activity activity) {
            super(activity);
        }
    
        @Override
        public State edit() {
            System.out.println("已开启无法编辑");
            return this;
        }
    
        @Override
        public State save() {
            System.out.println("已开启无法保存");
            return this;
        }
    
        @Override
        public State submit() {
            System.out.println("已开启无法提交");
            return this;
        }
    
        @Override
        public State pass() {
            System.out.println("已开启无法审核");
            return this;
        }
    
        @Override
        public State reject() {
            System.out.println("已开启无法审核");
            return this;
        }
    
        @Override
        public State start() {
            System.out.println("已开启无法再次开启");
            return this;
        }
    
        @Override
        public State close() {
            System.out.println("活动已经关闭");
            return activity.changeState(new CloseState(activity));
        }
    }
    
    
    package com.cloud.bssp.designpatterns.state;
    
    /**
     * 关闭状态
     * @date: 2021/1/25
     * @author weirx
     * @version 3.0
     */
    public class CloseState extends State{
    
        public CloseState(Activity activity) {
            super(activity);
        }
    
        @Override
        public State edit() {
            System.out.println("活动正在编辑中");
            return activity.changeState(new EditState(activity));
        }
    
        @Override
        public State save() {
            System.out.println("关闭状态无法保存");
            return this;
        }
    
        @Override
        public State submit() {
            System.out.println("关闭状态无法提交");
            return this;
        }
    
        @Override
        public State pass() {
            System.out.println("关闭状态无法再次审核");
            return this;
        }
    
        @Override
        public State reject() {
            System.out.println("关闭状态无法再次审核");
            return this;
        }
    
        @Override
        public State start() {
            System.out.println("关闭状态无法开启");
            return this;
        }
    
        @Override
        public State close() {
            System.out.println("关闭状态无法再次关闭");
            return this;
        }
    
    }
    
    

    测试类:

    package com.cloud.bssp.designpatterns.state;
    
    /**
     * 测试
     * @date: 2021/1/25
     * @author weirx
     * @version 3.0
     */
    public class TestDemo {
    
        public static void main(String[] args) {
            //初始化活动
            Activity activity = new Activity("1", "活动1");
            //初始化编辑状态
            State state = new EditState(activity);
            //保存
            state = state.save();
            //提交
            state = state.submit();
            //审核通过
            state = state.pass();
            //开启
            state = state.start();
            //开启状态下编辑
            state.edit();
            //开启状态下提交
            state.submit();
        }
    }
    
    

    结果:

    活动已保存
    活动已提交
    活动已经审核通过
    活动已经开启
    已开启无法编辑
    已开启无法提交
    

    4、分析

    State.png

    如上图所示,看到各个关系之间错综复杂,在每种状态里面不同的操作,会返回不同的状态结果,且对于其他状态没有影响。在Activity这个类里面,提供了一个公共的状态改变方法,只需声明局部变量State。

    以上方式利于扩展,每个状态各司其职,充分解耦。

    缩减上面的状态,以编辑状态为例,总结状态模式的几个主要组成如下图:

    State.png

    TestDemo:客户端。
    State:顶层抽象。
    Activity:状态上下文。
    EditState:具体当前状态。

    5、总结

    优点:
    1)单一职责原则。 将与特定状态相关的代码放在单独的类中。
    2)开闭原则。 无需修改已有状态类和上下文就能引入新状态。
    3)通过消除臃肿的状态机条件语句简化上下文代码。
    缺点:
    如果状态机只有很少的几个状态, 或者很少发生改变, 那么应用该模式可能会显得小题大作。

    相关文章

      网友评论

        本文标题:设计模式(二十)状态模式

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