何时使用

State模式在实际使用中比较多,适合“状态”的切换。因为我们经常会使用If else if else 进行状态切换,如果针对状态的这样判断切换反复出现,我们就要联想到是否可以采取State模式了。

这里要阐述的是"开关切换状态" 和" 一般的状态判断"是有一些区别的," 一般的状态判断"也是有 if..elseif结构,例如:

[java] view plain copy  print?

  1. if (which==1) state="hello";
  2. else if (which==2) state="hi";
  3. else if (which==3) state="bye";

这是一个 " 一般的状态判断”,state值的不同是根据which变量来决定的,which和state没有关系.如果改成:

[java] view plain copy  print?

  1. if (state.euqals("bye")) state="hello";
  2. else if (state.euqals("hello")) state="hi";
  3. else if (state.euqals("hi")) state="bye";

这就是 "开关切换状态”,是将state的状态从"hello"切换到”hi",再切换到"”bye",在切换到”hello",好象一个旋转开关,这种状态改变就可以使用State模式了。

如果单纯有上面一种将"hello"-->"hi"-->"bye"-->"hello"这一个方向切换,也不一定需要使用State模式,因为State模式会建立很多子类,复杂化,但是如果又发生另外一个行为:将上面的切换方向反过来切换,或者需要任意切换,就需要State了。

下面是一个一般写法的状态切换

[java] view plain copy  print?

  1. public class Context{
  2.   private Color state=null;
  3.   public void push(){
  4.     //如果当前red状态,切换到blue
  5.     if (state==Color.red) state=Color.blue;
  6.     //如果当前blue状态,切换到green
  7.     else if (state==Color.blue) state=Color.green;
  8.     //如果当前black状态,切换到red
  9.     else if (state==Color.black) state=Color.red;
  10.     //如果当前green状态,切换到black
  11.     else if (state==Color.green) state=Color.black;
  12.     Sample sample=new Sample(state);
  13.     sample.operate();
  14.   }
  15.   public void pull(){
  16.     //与push状态切换正好相反
  17.     if (state==Color.green) state=Color.blue;
  18.     else if (state==Color.black) state=Color.green;
  19.     else if (state==Color.blue) state=Color.red;
  20.     else if (state==Color.red) state=Color.black;
  21.     Sample2 sample2=new Sample2(state);
  22.     sample2.operate();
  23.   }
  24. }

使用策略模式重写上面例子

State需要两种类型实体参与:

1.state manager 状态管理器 ,就是开关 ,如上面例子的Context实际就是一个state manager, 在state manager中有对状态的切换动作.

2.用抽象类或接口实现的父类,,不同状态就是继承这个父类的不同子类.

首先建立一个父类

[java] view plain copy  print?

  1. public abstract class State{
  2.   public abstract void handlepush(Context c);
  3.   public abstract void handlepull(Context c);
  4.   public abstract void getcolor();
  5. }

父类中的方法要对应state manager中的开关行为,在state manager中本例就是Context中,有两个开关动作push推和pull拉.

那么在状态父类中就要有具体处理这两个动作:handlepush() handlepull(); 同时还需要一个获取push或pull结果的方法getcolor()

下面是具体子类的实现

状态切换顺序

push:blue-->green-->black-->red-->blue

pull:blue-->red-->black-->green-->blue

[java] view plain copy  print?

  1. public class BlueState extends State{
  2.   public void handlepush(Context c){
  3. System.out.println(“变成绿色");
  4.      c.setState(new GreenState());
  5.   }
  6.   public void handlepull(Context c){
  7. System.out.println(“变成红色");
  8.     c.setState(new RedState());
  9.   }
  10.   public abstract void getcolor(){
  11. return (Color.blue);
  12. }
  13. }

[java] view plain copy  print?

  1. public class GreenState extends State{
  2.   public void handlepush(Context c){
  3. System.out.println(“变成黑色");
  4.      c.setState(new BlackState());
  5.   }
  6.   public void handlepull(Context c){
  7. System.out.println(“变成蓝色");
  8.      c.setState(new BlueState());
  9.   }
  10.   public abstract void getcolor(){
  11. return (Color.green);
  12. }
  13. }

[java] view plain copy  print?

  1. public class BlackState extends State{
  2.   public void handlepush(Context c){
  3. System.out.println(“变成红色");
  4.      c.setState(new RedState());
  5.   }
  6.   public void handlepull(Context c){
  7. System.out.println(“变成红色");
  8.     c.setState(new RedState());
  9.   }
  10.   public abstract void getcolor(){
  11. return (Color.black);
  12. }
  13. }

[java] view plain copy  print?

  1. public class RedState extends State{
  2.   public void handlepush(Context c){
  3. System.out.println(“变成蓝色");
  4.      c.setState(new BlueState());
  5.   }
  6.   public void handlepull(Context c){
  7. System.out.println(“变成黑色");
  8.     c.setState(new BlackState());
  9.   }
  10.   public abstract void getcolor(){
  11. return (Color.red);
  12. }
  13. }

重新改写State manager 也就是本例的Context

[java] view plain copy  print?

  1. public class Context{
  2.   private Sate state=null; //我们将原来的 Color state 改成了新建的State state;
  3.   //setState是用来改变state的状态 使用setState实现状态的切换
  4.   pulic void setState(State state){
  5.     this.state=state;
  6.   }
  7.   public void push(){
  8.     //状态的切换的细节部分,在本例中是颜色的变化,已经封装在子类的handlepush中实现,这里无需关心
  9.     state.handlepush(this);
  10.     //假设sample要使用state中的一个切换结果,使用getColor()
  11.     Sample sample=new Sample(state.getColor());
  12.     sample.operate();
  13.   }
  14.   public void pull(){
  15.     state.handlepull(this);
  16. //假设sample要使用state中的一个切换结果,使用getColor()
  17.     Sample2 sample2=new Sample2(state.getColor());
  18.     sample2.operate();
  19.   }
  20. }

状态模式在工作流或游戏等各种系统中有大量使用,甚至是这些系统的核心功能设计,例如ERP系统中,一个批文的状态有多种:未办;正在办理;正在批示;正在审核;已经完成等各种状态,使用状态机可以封装这个状态的变化规则,从而达到扩充状态时,不必涉及到状态的使用者。

总结

使用状态模式前,客户端外界需要介入改变状态,而状态改变的实现是琐碎或复杂的。

使用状态模式后,客户端外界可以直接使用事件Event实现,根本不必关心该事件导致如何状态变化,这些是由状态机等内部实现。

这是一种Event-condition-State,状态模式封装了condition-State部分。

每个状态形成一个子类,每个状态只关心它的下一个可能状态,从而无形中形成了状态转换的规则。如果新的状态加入,只涉及它的前一个状态修改和定义。

状态模式的主要优点在于封装了转换规则,并枚举可能的状态,它将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为,还可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数;其缺点在于使用状态模式会增加系统类和对象的个数,且状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱,对于可以切换状态的状态模式不满足“开闭原则”的要求。

欢迎关注公众号:

【状态模式】Java设计模式之状态模式相关推荐

  1. java之备忘录模式,java设计模式之备忘录模式

    java设计模式之备忘录模式 代码无错便是优? 简介: 在不破坏封装性的前提下 , 捕获一个对象的内部状态,并在该对象之外保存这个状态 , 这样以后就可以将该对象恢复到原先保存的状态 . 备忘录模式就 ...

  2. Java设计模式分为创建模式, 结构模式, 行为模式 3种类型

    Java设计模式之创建模式包括: Factory,    工厂模式 Singleton,   单例模式 Builder,    建造模式 Prototype,    原型模式 Java设计模式之结构模 ...

  3. JAVA设计模式 - 创建型模式总结

    JAVA设计模式 - 单例模式 JAVA设计模式 - 工厂方法模式 JAVA设计模式 - 抽象工厂模式 JAVA设计模式 - 原型模式 JAVA设计模式 - 建造者模式 1 . 创建型模式的定义 顾名 ...

  4. Java设计模式之Builder模式

    Java设计模式之Builder模式 Java设计模式之Builder模式 简介 适用性 用LOL的出装备的顺序为例 基本实现代码 BasePerson的实现 DeMaXiYa的实现 QiTianDa ...

  5. Java 设计模式之Builder模式

    设计模式系列 创建型设计模式 Java 设计模式之单例模式 Java 设计模式之静态工厂方法模式 Java 设计模式之工厂方法模式 Java 设计模式之抽象工厂模式 Java 设计模式之Builder ...

  6. Java设计模式之策略模式与状态模式

    一.策略模式定义 定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们之间可以相互替换,策略模式可以在不影响客户端的情况下发生变化. 好了,定义看看就完了,我知道你很烦看定义. 二.策 ...

  7. java设计模式之状态模式_Java中的状态设计模式

    java设计模式之状态模式 在本教程中,我们将探讨另一种流行的行为设计模式-状态设计模式. 当我们使用可以存在于多个状态的对象时,状态设计模式的知识变得非常有用. 当对象的行为取决于其当前状态时,我们 ...

  8. 图解java多线程设计模式 pdf_图解Java设计模式之状态模式

    图解Java设计模式之状态模式 APP抽象活动问题 状态模式基本介绍 状态模式的原理类图 状态模式解决APP抽奖问题 状态模式的注意事项和细节 APP抽象活动问题 请编写程序完成APP抽象活动,具体要 ...

  9. java备忘录模式应用场景_图解Java设计模式之备忘录模式

    图解Java设计模式之备忘录模式 游戏角色状态恢复问题 游戏角色有攻击力和防御力,在大战Boss前保存自身的状态(攻击力和防御力),当大战Boss后攻击力和防御力下降,从备忘录对象恢复到大战前的状态. ...

  10. Java设计模式(访问者模式-迭代器模式-观察者模式-中介者模式)

    Java设计模式Ⅶ 1.访问者模式 1.1 访问者模式概述 1.2 代码理解 2.迭代器模式 2.1 迭代器模式概述 2.2 代码理解 3.观察者模式 3.1 观察者模式概述 3.2 代码理解 4.中 ...

最新文章

  1. 图解计算机中数据的表示形式
  2. Material Designer的低版本兼容实现(十)—— CheckBox RadioButton
  3. Spring控制器响应(action)请求的几种处理方式,如返回JSON,MODEL MODELVIEW,STRING
  4. 树结构(三)----线索二叉树
  5. boost / vs2017 编译 boost 1.68.0 的过程说明
  6. JVM监控工具介绍jstack, jconsole, jinfo, jmap, jdb, jsta (Linux 如何查看进程的各线程的CPU占用 )
  7. eclipse+pydev添加已存在django项目及其调试方法
  8. Dubbo 需求、架构、使用Demo
  9. navicat for mysql 数据库备份与还原
  10. 2021年新高考八省联考成绩查询福建,八省联考福建什么时候出成绩 2021八省联考福建成绩查询...
  11. 了解SQL Server SELECT INTO语句
  12. Android开发之桌面快捷键使用细则(原创)
  13. 蝉妈妈对话曹颖:5月带货1.1亿,踩过的坑都变成了卖货的筹码
  14. 音视频学习(三)——sip协议
  15. simulink中对powergui的使用
  16. 程序员必备利器:8 款“珍藏已久”的程序开发利器,瞬间提升效率
  17. 72 个网络应用安全实操要点,全方位保护你的 Web 应用
  18. 合理的网页设计具有哪些特征
  19. Android MOCK HTTP 接口新方式
  20. 可视化神器Plotly绘制3D图

热门文章

  1. 记一次突然宕机重启服务器导致docker中redis无法启动的问题解决
  2. F1赛道 - Bahrain International Circuit | 巴林国际赛道
  3. 阿里云智能总裁、达摩院院长张建锋2020云栖大会最新完整版演讲全文
  4. linux shell 命令之 uname
  5. php_uname()函数
  6. 存储过程排版工具_文案创作者必备的7个写作辅助工具类网站,记得收藏
  7. matlab纹理柱状图程序
  8. 夜神模拟器如何把模拟器里的文件拷出来呢 亲测
  9. storm mysql trident_Storm Trident状态
  10. go语言单元测试报错:missing go.sum entry for module providing package github.com/stretchr/testify/assert