本文从简单的例子入手,逐步演变成非常复杂的程序。

在简明 状态模式(5.8)中,状态之间的变换由外界控制,或者说,多种状态是分割的、无关的。状态模式最有趣的地方正是讨论其状态的变迁。

1.引子

空调(air-condition)的遥控器有两个按钮(更多的按钮在后面的例子中引入),power/电源键和cool/制冷键。空调的运行呈现3个状态,停止/Off、仅送风/FanOnly、制冷/Cool。起始状态为Off,状态变化图如下所示。

这是简化的有限状态机(Finite State Machine、FSM或者Finite State Automata)图形,使用了状态图的3个元素:①气泡,表示状态(state);②连接状态的箭头表示转换(transition);③箭头上的标记前者为事件(event)。

状态的转换,看图说话。按power键,则Off→FanOnly、Cool→Off等;按cool,则Off→Off (没有画出来,喜欢全面一点就自己画吧)。

对于这种简单的状态的转换,yqj2065还是喜欢分支语句,简洁明快。

  1.  
  2. [java] view plain copy
  3.  
  4. 例程 4-5 简洁明快
  5. package property.state.stateMachine;
  6. import static tool.Print.*;//pln
  7. /**
  8. * 空调Aircon。简单的模型:
  9. * 遥控器有两个按钮(更多的按钮在下面的例子中引入),power电源键和cool制冷键。
  10. * 空调的运行呈现3个状态,停止/Off、仅送风/FanOnly、制冷/Cool。
  11. * 起始状态为Off
  12. * @author (yqj2065)
  13. * @version 0.1
  14. */
  15. public class Aircon0{
  16. // off,FanOnly,AC
  17. private int state=0;//起始状态为Off
  18. public int getState(){return state;}
  19. //两个Action
  20. public void power(){//按power键
  21. if(state==0){//off
  22. state=1;
  23. pln("start Fan");
  24. }else if(state==1){//FanOnly
  25. state=0;
  26. pln("stop Fan");
  27. }else{
  28. state=0;
  29. pln("stop Cool");
  30. }
  31. }
  32.  
  33. public void cool(){//按制冷键
  34. if(state==0){//off
  35. pln("nothing");
  36. }else if(state==1){//FanOnly
  37. state=2;
  38. pln("start Cool");
  39. }else{
  40. state=1;
  41. pln("stop Cool");
  42. }
  43. }
  44. }
  45. package property.state.stateMachine;
  46. public class ACCtrl{
  47. public static void test(){
  48. Aircon0 ac = new Aircon0();//power() cool()
  49. System.out.println("Current State:" + ac.getState());
  50. ac.cool();
  51. ac.power();
  52. ac.cool();
  53. ac.cool();
  54. ac.power();
  55. ac.power();
  56. }
  57. }
  58. 测试代码的输出:
  59.  
  60. Current State:0
  61. nothing
  62. start Fan
  63. start Cool
  64. stop Cool
  65. stop Fan
  66. start Fan

  

在此基础上,可以花10分钟练习一下,采用状态模式修改上述代码。我们使用enum编写状态类层次。其结构如下:

  1. [java] view plain copy
  2.  
  3. 例程 4 6 enum State
  4.  
  5. enum State0{
  6. OFF{
  7. @Override void power(){
  8. }
  9. @Override void power(){
  10. }
  11. },FANONLY{
  12. },
  13. COOL{ };
  14. public abstract void power();
  15. public abstract void cool();
  16. }
  17. (本来是应该将State1作为Aircon1的内部类的。放在外边,power()等需要添加参数Aircon1,变为power(Aircon1 ac)).
  18.  
  19. 现在,丰富有限状态机的细节,增添④动作(action),如事件(event)相应的动作和状态的动作。
  20.  
  21. 为此,在enum State1中,除了状态模式 提取的接口外,添加了状态机的各种动作/action methode
  22. void entry(Aircon1 ac){pln("→"+ac.state.name());}
  23. void exit(Aircon1 ac){p(ac.state.name()+"→ ");}
  24. void startCool(){ p("start Cool"); }
  25. void stopCool(){ p("stop Cool"); }
  26. void startFan(){ p("start Fan"); }
  27. void stopFan(){ p("stop Fan"); }
  28.  
  29. 每个power(Aircon1 ac)、cool(Aircon1 ac)的方法体结构都是:
  30.  
  31. this.exit(ac);
  32. //如果有的话,事件(event)相应的动作,如stopFan();
  33. ac.state =OFF; //下一个状态
  34. ac.state.entry(ac);
  35.  
  36. [java] view plain copy
  37.  
  38. package property.state.stateMachine;
  39. import static tool.Print.*;//pln
  40. /**
  41. * 本来是应该将State1作为Aircon1的内部类的。现在放在外边,
  42. * power()等需要变为power(Aircon1 ac)
  43. */
  44. public enum State1{
  45. OFF{
  46. @Override void exit(Aircon1 ac){super.exit(ac);startFan();}
  47. @Override void power(Aircon1 ac){
  48. this.exit(ac);
  49. ac.state =FANONLY;
  50. ac.state.entry(ac);
  51. }
  52. @Override void cool(Aircon1 ac){
  53. pln("nothing");
  54. }
  55. },FANONLY{
  56. @Override void power(Aircon1 ac){
  57. this.exit(ac);
  58. stopFan();
  59. ac.state =OFF;
  60. ac.state.entry(ac);
  61. }
  62. @Override void cool(Aircon1 ac){
  63. this.exit(ac);
  64. ac.state =COOL;
  65. ac.state.entry(ac);
  66. }
  67. },
  68. COOL{
  69. @Override void exit(Aircon1 ac){super.exit(ac);stopCool();}
  70. @Override void entry(Aircon1 ac){startCool();super.entry(ac);}
  71. @Override void power(Aircon1 ac){
  72. this.exit(ac);
  73. stopFan();
  74. ac.state =OFF;
  75. ac.state.entry(ac);
  76. }
  77. @Override void cool(Aircon1 ac){
  78. this.exit(ac);
  79. ac.state =FANONLY;
  80. ac.state.entry(ac);
  81. }
  82. };
  83. //状态模式 提取的接口
  84. abstract void power(Aircon1 ac);
  85. abstract void cool(Aircon1 ac);
  86. //状态机的各种动作action methode
  87. void entry(Aircon1 ac){pln("→"+ac.state.name());}
  88. void exit(Aircon1 ac){p(ac.state.name()+"→ ");}
  89. void startCool(){ p("start Cool"); }
  90. void stopCool(){ p("stop Cool"); }
  91. void startFan(){ p("start Fan"); }
  92. void stopFan(){ p("stop Fan"); }
  93. }

  

空调Aircon1的修改版本。

  1. [java] view plain copy
  2.  
  3. package property.state.stateMachine;
  4. import static tool.Print.*;//pln
  5. /**
  6. * 空调Aircon1。使用状态模式重构Aircon0,使用enum State1编写状态类层次。
  7. * @author (yqj2065)
  8. * @version 0.1
  9. */
  10. public class Aircon1{
  11. State1 state= State1.OFF;//private改默认,删除getState()。
  12. //两个Action
  13. public void power(){//按power键
  14. state.power(this);
  15. }
  16. public void cool(){//按制冷键
  17. state.cool(this);
  18. }
  19. /**
  20. * ACCtrl的代码。
  21. */
  22. public static void test(){
  23. Aircon1 ac = new Aircon1();
  24. System.out.println("Current State:" + ac.state.name());
  25. ac.cool();
  26. ac.power();
  27. ac.cool();
  28. ac.cool();
  29. ac.power();
  30. ac.power();
  31. ac.power();
  32.  
  33. }
  34. }

  

 

对应测试操作的输出:“OFF→”表示离开OFF状态,而“→FANONLY”...

Current State:OFF
nothing
OFF→ start Fan→FANONLY
FANONLY→ start Cool→COOL
COOL→ stop Cool→FANONLY
FANONLY→ stop Fan→OFF
OFF→ start Fan→FANONLY
FANONLY→ stop Fan→OFF

2.分层状态机

对于状态较多的状态机,通常将具有许多公共的特性的状态合并到一起。例如FANONLY和COOL构成的Running状态

状态机中的hierarchical states,我们可以使用组合模式处理。(还没有单独写组合模式,)。但是,又不一定能够完美地使用组合模式,例如Running到Off,所有的Running的内部状态在PoverEvent时都转化到OFF,很好;OFF到Running,不是所有Running的内部状态都要调用其entry。在使用enum(不好搞类层次)时,使用责任链吧。

搜集摘抄于:http://blog.csdn.net/yqj2065/article/details/39371487

有限状态机(FSM)的Java 学习FSM的更多相关文章

  1. 有限状态机(FSM)的Java 演示

    本文从简单的样例入手,逐步演变成很复杂的程序. 在简明 状态模式(5.8)中,状态之间的变换由外界控制,或者说.多种状态是切割的.无关的.状态模式最有趣的地方正是讨论其状态的变迁. 1.引子 空调(a ...

  2. Atitit.java expression fsm 表达式词法分析引擎 v2 qaa.docx

    Atitit.java expression fsm 表达式词法分析引擎 v2 qaa.docx C:\0workspace\AtiPlatf_cms\src\com\attilax\fsm\Java ...

  3. Atitit.java expression fsm 表达式分词fsm引擎

    Atitit.java expression fsm 表达式分词fsm引擎 C:\0workspace\AtiPlatf_cms\src\com\attilax\fsm\JavaExpFsm.java ...

  4. 0037 Java学习笔记-多线程-同步代码块、同步方法、同步锁

    什么是同步 在上一篇0036 Java学习笔记-多线程-创建线程的三种方式示例代码中,实现Runnable创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ...

  5. 0035 Java学习笔记-注解

    什么是注解 注解可以看作类的第6大要素(成员变量.构造器.方法.代码块.内部类) 注解有点像修饰符,可以修饰一些程序要素:类.接口.变量.方法.局部变量等等 注解要和对应的配套工具(APT:Annot ...

  6. 分享篇——我的Java学习路线

    虽然之前我是开发出身,但是我学习的语言是Objective-c,这个语言使用起来范围比较窄,对于自动化学习来说也是无用武之地,所以我自己学习了Java,对于一个有开发经验的人来说学习一门新语言相对来说 ...

  7. Java学习笔记(04)

    Java学习笔记(04) 如有不对或不足的地方,请给出建议,谢谢! 一.对象 面向对象的核心:找合适的对象做合适的事情 面向对象的编程思想:尽可能的用计算机语言来描述现实生活中的事物 面向对象:侧重于 ...

  8. Java学习心得之 HttpClient的GET和POST请求

    作者:枫雪庭 出处:http://www.cnblogs.com/FengXueTing-px/ 欢迎转载 Java学习心得之 HttpClient的GET和POST请求 1. 前言2. GET请求3 ...

  9. 0032 Java学习笔记-类加载机制-初步

    JVM虚拟机 Java虚拟机有自己完善的硬件架构(处理器.堆栈.寄存器等)和指令系统 Java虚拟机是一种能运行Java bytecode的虚拟机 JVM并非专属于Java语言,只要生成的编译文件能匹 ...

随机推荐

  1. Http请求中Content-Type讲解以及在Spring MVC注解中produce和consumes配置详解

    原文地址:  https://blog.csdn.net/shinebar/article/details/54408020 引言: 在Http请求中,我们每天都在使用Content-type来指定不 ...

  2. NIO中的heap Buffer和direct Buffer区别

    在Java的NIO中,我们一般采用ByteBuffer缓冲区来传输数据,一般情况下我们创建Buffer对象是通过ByteBuffer的两个静态方法: ByteBuffer.allocate(int c ...

  3. Win2008建立域时administrator账户密码不符合要求

    在win2008中建立域时,有时会出现administrator账户密码不符合要求的现象,报错会说明目前本地administrator账户不需要密码.这是什么原因造成的呢?原来,目前的2008镜像在网 ...

  4. CListCtrl 之右键菜单

    在使用CListCtrl时要为它添加一个右键菜单,步骤如下: 1. 响应CListCtrl的NM_RCLICK消息. 2. 添加一个菜单资源,在菜单资源中插入要添加到菜单内容.   一般存在两种方法: ...

  5. [leetcode]Subsets @ Python

    原题地址:https://oj.leetcode.com/problems/subsets/ 题意:枚举所有子集. 解题思路:碰到这种问题,一律dfs. 代码: class Solution: # @ ...

  6. iOS开发-16进制颜色转换

    项目中经常会用到颜色转换,有的是通过十六进制转成数字转颜色,想简单的点直接通过字符串转一下,简单扩展了一下分类UIColor,代码如下: +(UIColor *)colorWithHex:(NSStr ...

  7. Binary Tree Level Order Traversal II leetcode java

    题目: Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from ...

  8. Java奇淫巧技之Lombok

    http://blog.csdn.net/ghsau/article/details/52334762

  9. GDB 程序调试简单实践

    用了好久的GCC/G++ 却一直都没用过GDB调试过程序,有时程序不是非常大,一般有错,直接看编译器编译结果就几乎相同知道错在哪儿了,或者使用codeblocks单步调试,甚至回到windows以下调 ...

  10. Swift编程语言学习1.7——断言

    断言 可选能够让你推断值是否存在,你能够在代码中优雅地处理值缺失的情况.然而,在某些情况下,假设值缺失或者值并不满足特定的条件,你的代码可能并不须要继续执行.这时.你能够在你的代码中触发一个断言(as ...