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

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

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

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

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

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

原来的实现:

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

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

现有的实现:

1. 状态类

1. 1 状态类的接口

  1. /**
  2. * 状态接口
  3. */
  4. public interface State {
  5. /**
  6. * 1. 拿杯子
  7. */
  8. void takeCup();
  9. /**
  10. * 2. 往杯子中添加速溶咖啡
  11. */
  12. void addInstantCoffe();
  13. /**
  14. * 3. 往杯子中加水
  15. */
  16. void addWater();
  17. /**
  18. * 4. 尽情的享受咖啡
  19. */
  20. void enjoyCoffe();
  21. }

1.2 没有杯子的状态类

  1. /**
  2. * 0. 没有杯子的状态
  3. */
  4. public class NoCupState implements State {
  5. private MakeCoffe makeCoffe;
  6. public NoCupState(MakeCoffe makeCoffe) {
  7. this.makeCoffe = makeCoffe;
  8. }
  9. @Override
  10. public void takeCup() {
  11. makeCoffe.state = makeCoffe.emptyCupState;
  12. System.out.println("拿了一个杯子");
  13. }
  14. @Override
  15. public void addInstantCoffe() {
  16. System.out.println("还没有一个杯子, 需要拿个杯子");
  17. }
  18. @Override
  19. public void addWater() {
  20. System.out.println("还没有一个杯子, 需要拿个杯子");
  21. }
  22. @Override
  23. public void enjoyCoffe() {
  24. System.out.println("现在还没有杯子, 享受不了啊");
  25. }
  26. }

1.3 空杯子的状态

  1. /**
  2. * 1. 有个空杯子的状态
  3. */
  4. public class EmptyCupState implements State {
  5. private MakeCoffe makeCoffe;
  6. public EmptyCupState(MakeCoffe makeCoffe) {
  7. this.makeCoffe = makeCoffe;
  8. }
  9. @Override
  10. public void takeCup() {
  11. System.out.println("已经有个空杯子了, 不需要再");
  12. }
  13. @Override
  14. public void addInstantCoffe() {
  15. this.makeCoffe.state = makeCoffe.instantCoffeCupState;
  16. System.out.println("往杯子加了速溶咖啡");
  17. }
  18. @Override
  19. public void addWater() {
  20. System.out.println("杯子中还需要先加速溶咖啡粉, 再加水");
  21. }
  22. @Override
  23. public void enjoyCoffe() {
  24. System.out.println("现在还是空杯子, 享受不了啊");
  25. }
  26. }

1.4 加了速溶咖啡的状态

  1. /**
  2. * 2. 加了速溶咖啡的状态
  3. */
  4. public class InstantCoffeCupState implements State {
  5. private MakeCoffe makeCoffe;
  6. public InstantCoffeCupState(MakeCoffe makeCoffe) {
  7. this.makeCoffe = makeCoffe;
  8. }
  9. @Override
  10. public void takeCup() {
  11. System.out.println("杯子中已经加了速溶咖啡了, 不需要在拿一个了");
  12. }
  13. @Override
  14. public void addInstantCoffe() {
  15. System.out.println("杯子中已经加了速溶咖啡了, 不需要再放速溶咖啡了");
  16. }
  17. @Override
  18. public void addWater() {
  19. makeCoffe.state = makeCoffe.coffeOkState;
  20. System.out.println("往有速溶咖啡的杯子里, 加水");
  21. }
  22. @Override
  23. public void enjoyCoffe() {
  24. System.out.println("现在杯子中还没加水, 享受不了啊");
  25. }
  26. }

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

  1. /**
  2. * 4. 咖啡冲好, 享受咖啡
  3. */
  4. public class CoffeOkState implements State {
  5. @Override
  6. public void takeCup() {
  7. System.out.println("咖啡已经冲好了, 不需要再拿一个杯子了");
  8. }
  9. @Override
  10. public void addInstantCoffe() {
  11. System.out.println("咖啡已经冲好了, 不需要再加速溶咖啡了");
  12. }
  13. @Override
  14. public void addWater() {
  15. System.out.println("咖啡已经冲好了, 不需要再加水了");
  16. }
  17. @Override
  18. public void enjoyCoffe() {
  19. System.out.println("享受咖啡咯");
  20. }
  21. }

2. 制作咖啡的类

  1. /**
  2. * 制作咖啡的类
  3. */
  4. public class MakeCoffe {
  5. /**
  6. * 这杯咖啡的状态
  7. */
  8. public State state;
  9. /**
  10. * 没有杯子状态
  11. */
  12. public NoCupState noCupState;
  13. /**
  14. * 有一个空杯子状态
  15. */
  16. public EmptyCupState emptyCupState;
  17. /**
  18. * 杯子里有速溶咖啡粉状态
  19. */
  20. public InstantCoffeCupState instantCoffeCupState;
  21. /**
  22. * 冲好咖啡状态
  23. */
  24. public CoffeOkState coffeOkState;
  25. public MakeCoffe() {
  26. this.noCupState = new NoCupState(this);
  27. this.emptyCupState = new EmptyCupState(this);
  28. this.instantCoffeCupState = new InstantCoffeCupState(this);
  29. this.coffeOkState = new CoffeOkState();
  30. // 设置默认状态
  31. this.state = this.noCupState;
  32. }
  33. // 拿杯子
  34. public void takeCup() {
  35. state.takeCup();
  36. }
  37. // 加入速溶咖啡
  38. public void addInstantCoffe() {
  39. state.addInstantCoffe();
  40. }
  41. // 加水
  42. public void addWater() {
  43. state.addWater();
  44. }
  45. public void enjoyCoffe() {
  46. state.enjoyCoffe();
  47. }
  48. }

3. 测试

  1. /**
  2. * 享受咖啡测试类
  3. */
  4. public class EnjoyCoffeMain {
  5. public static void main(String[] args) {
  6. MakeCoffe makeCoffe = new MakeCoffe();
  7. makeCoffe.takeCup();
  8. makeCoffe.addInstantCoffe();
  9. makeCoffe.addWater();
  10. makeCoffe.enjoyCoffe();
  11. }
  12. }
  13. // 控制台显示
  14. 拿了一个杯子
  15. 往杯子加了速溶咖啡
  16. 往有速溶咖啡的杯子里, 加水
  17. 享受咖啡咯

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

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

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

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

版权声明:本文为milicool原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/milicool/p/11278671.html