博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
状态模式的理解和示例
阅读量:4550 次
发布时间:2019-06-08

本文共 5095 字,大约阅读时间需要 16 分钟。

一、是什么

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. 带来的缺点就是,增加了很多的类

三、总结

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

转载于:https://www.cnblogs.com/milicool/p/11278671.html

你可能感兴趣的文章
题目2
查看>>
js创建对象的方式 三种
查看>>
elementUI vue v-model的修饰符
查看>>
数组复制:关于java中引用传递的一个例子
查看>>
第九周PSP
查看>>
红帽linux忘记root密码的配置
查看>>
JS十进制转二进制(控制位数)
查看>>
Spark源码分析 – SparkContext
查看>>
tabBar选择不同item设置标题不同颜色
查看>>
机器学习算法一览图
查看>>
【BZOJ】3309: DZY Loves Math 莫比乌斯反演优化
查看>>
luogu1972:HH的项链
查看>>
矩形面积
查看>>
C++语言 文件对话框的调用
查看>>
运算符
查看>>
11.软件项目管理与敏捷方法——风险管理笔记
查看>>
微服务监控zipkin、skywalking以及日志ELK监控系列
查看>>
4553: [Tjoi2016&Heoi2016]序列
查看>>
3027 线段覆盖 2
查看>>
CF 959 E. Mahmoud and Ehab and the xor-MST
查看>>