• 状态模式的理解和示例


    一、是什么

    1. 定义: 封装了基于状态的行为,并使用委托在行为之间切换

    2. 好处: 通过将每个状态封装到类中,将以后需要做的任何改变局部化

    3. 缺点: 使用状态类通常会导致设计类的数量大量增加

    4. 类图如上,和策略模式的类图相同,目的不同,策略是为了封装互换的行为,用委托来解耦,状态模式的目的是将状态封装成类,用委托来切换状态

    二、示例

    场景:假设冲一杯咖啡的步骤是,1. 拿一个空杯子 2. 往杯子中添加速溶咖啡 3. 往杯子中加水

    该场景中有三个状态: 1. 空杯子 2. 装有速溶咖啡的杯子 2. 装水的杯子

    原来的实现:

      写了个大概的假代码, 这里只有拿杯子的方法,里面就有了四个if判断, 后面的方法还是继续if判断,相对麻烦一点, 当然最重要的是如果以后要变化步骤的话,整个类都在影响范围之类。而状态模式在这里可以帮我们将变化局部化

    final static int NO_CUP = 0                    // 还没有杯子的状态
    final static int EMPTY_CUP = 1                 // 空杯
    final static int INSTANT_COFFEE_CUP = 2        // 装有速溶咖啡粉的杯子
    final static int ENJOY_CUP = 3                 // 冲好咖啡, 美滋滋的杯子
    
    // 拿杯子的方法
    public void takeCup() {
        if (state == NO_CUP) {
            // 此时没有杯子, 所以我就拿了一个空杯子
            state = EMPTY_CUP;
        } else if (state == EMPTY_CUP) {
            // 已经有一个空杯子了, 不需要再拿了
        } else if (state == INSTANT_COFFEE_CUP) {
            // 已经有一个装有速溶咖啡粉的杯子, 不需要再拿了
        } else if (state == ENJOY_CUP) {
            // 已经冲好咖啡了, 不需要再拿了
        }
    }

    现有的实现:

    1. 状态类

    1. 1 状态类的接口

    /**
     * 状态接口
     */
    public interface State {
    
        /**
         * 1. 拿杯子
         */
        void takeCup();
    
        /**
         * 2. 往杯子中添加速溶咖啡
         */
        void addInstantCoffe();
    
        /**
         * 3. 往杯子中加水
         */
        void addWater();
    
        /**
         * 4. 尽情的享受咖啡
         */
        void enjoyCoffe();
    }

    1.2 没有杯子的状态类

    /**
     * 0. 没有杯子的状态
     */
    public class NoCupState implements State {
        private MakeCoffe makeCoffe;
    
        public NoCupState(MakeCoffe makeCoffe) {
            this.makeCoffe = makeCoffe;
        }
    
        @Override
        public void takeCup() {
            makeCoffe.state = makeCoffe.emptyCupState;
            System.out.println("拿了一个杯子");
        }
    
        @Override
        public void addInstantCoffe() {
            System.out.println("还没有一个杯子, 需要拿个杯子");
        }
    
        @Override
        public void addWater() {
            System.out.println("还没有一个杯子, 需要拿个杯子");
        }
    
        @Override
        public void enjoyCoffe() {
            System.out.println("现在还没有杯子, 享受不了啊");
        }
    }

    1.3 空杯子的状态

    /**
     * 1. 有个空杯子的状态
     */
    public class EmptyCupState implements State {
        private MakeCoffe makeCoffe;
    
        public EmptyCupState(MakeCoffe makeCoffe) {
            this.makeCoffe = makeCoffe;
        }
    
        @Override
        public void takeCup() {
            System.out.println("已经有个空杯子了, 不需要再");
        }
    
        @Override
        public void addInstantCoffe() {
            this.makeCoffe.state = makeCoffe.instantCoffeCupState;
            System.out.println("往杯子加了速溶咖啡");
        }
    
        @Override
        public void addWater() {
            System.out.println("杯子中还需要先加速溶咖啡粉, 再加水");
        }
    
        @Override
        public void enjoyCoffe() {
            System.out.println("现在还是空杯子, 享受不了啊");
        }
    }

    1.4 加了速溶咖啡的状态

    /**
     * 2. 加了速溶咖啡的状态
     */
    public class InstantCoffeCupState implements State {
        private MakeCoffe makeCoffe;
    
        public InstantCoffeCupState(MakeCoffe makeCoffe) {
            this.makeCoffe = makeCoffe;
        }
    
        @Override
        public void takeCup() {
            System.out.println("杯子中已经加了速溶咖啡了, 不需要在拿一个了");
        }
    
        @Override
        public void addInstantCoffe() {
            System.out.println("杯子中已经加了速溶咖啡了, 不需要再放速溶咖啡了");
        }
    
        @Override
        public void addWater() {
            makeCoffe.state = makeCoffe.coffeOkState;
            System.out.println("往有速溶咖啡的杯子里, 加水");
        }
    
        @Override
        public void enjoyCoffe() {
            System.out.println("现在杯子中还没加水, 享受不了啊");
        }
    }

    1.5 加完水,咖啡冲好的状态,享受咖啡

    /**
     * 4. 咖啡冲好, 享受咖啡
     */
    public class CoffeOkState implements State {
        @Override
        public void takeCup() {
            System.out.println("咖啡已经冲好了, 不需要再拿一个杯子了");
        }
    
        @Override
        public void addInstantCoffe() {
            System.out.println("咖啡已经冲好了, 不需要再加速溶咖啡了");
        }
    
        @Override
        public void addWater() {
            System.out.println("咖啡已经冲好了, 不需要再加水了");
        }
    
        @Override
        public void enjoyCoffe() {
            System.out.println("享受咖啡咯");
        }
    }

    2. 制作咖啡的类

    /**
     * 制作咖啡的类
     */
    public class MakeCoffe {
    
        /**
         * 这杯咖啡的状态
         */
        public State state;
    
        /**
         * 没有杯子状态
         */
        public NoCupState noCupState;
        /**
         * 有一个空杯子状态
         */
        public EmptyCupState emptyCupState;
        /**
         * 杯子里有速溶咖啡粉状态
         */
        public InstantCoffeCupState instantCoffeCupState;
        /**
         * 冲好咖啡状态
         */
        public CoffeOkState coffeOkState;
    
        public MakeCoffe() {
            this.noCupState = new NoCupState(this);
            this.emptyCupState = new EmptyCupState(this);
            this.instantCoffeCupState = new InstantCoffeCupState(this);
            this.coffeOkState = new CoffeOkState();
    
            // 设置默认状态
            this.state = this.noCupState;
        }
    
        // 拿杯子
        public void takeCup() {
            state.takeCup();
        }
    
        // 加入速溶咖啡
        public void addInstantCoffe() {
            state.addInstantCoffe();
        }
    
        // 加水
        public void addWater() {
            state.addWater();
        }
    
        public void enjoyCoffe() {
            state.enjoyCoffe();
        }
    }

    3. 测试

    /**
     * 享受咖啡测试类
     */
    public class EnjoyCoffeMain {
    
        public static void main(String[] args) {
            MakeCoffe makeCoffe = new MakeCoffe();
    
            makeCoffe.takeCup();
            makeCoffe.addInstantCoffe();
            makeCoffe.addWater();
            makeCoffe.enjoyCoffe();
        }
    }
    
    // 控制台显示
    拿了一个杯子
    往杯子加了速溶咖啡
    往有速溶咖啡的杯子里, 加水
    享受咖啡咯

    1. 恭喜这个程序猿在没有写很多IF判断的情况下,成功享受到咖啡, 状态模式这里我觉得好处就是可以将变化分开封装,以后 要是某个状态中的操作改了,不需要查找整个IF了,找到对应类修改。

    2. 或者以后添加某个状态的话,如卡布奇诺需要加奶加糖等,就不需要修改IF, 而是添加状态,修改部分状态中的代码

    3. 带来的缺点就是,增加了很多的类

    三、总结

    想想自己两年前理解的状态的模式,现在比以前更理解一点了

  • 相关阅读:
    stl rope
    vijos1574 摇钱树
    图论 Dijkstra+堆优化
    c++输入优化
    Vijos1579 宿命的PSS 最小生成树
    快速求n阶多项式乘积
    c++stl map
    C#函数式程序设计之惰性列表工具——迭代器
    C#函数式程序设计之泛型(下)
    C#函数式程序设计之泛型(上)
  • 原文地址:https://www.cnblogs.com/milicool/p/11278671.html
Copyright © 2020-2023  润新知