有限状态机(FSM)的Java 学习FSM

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

在简明 状态模式(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还是喜欢分支语句,简洁明快。

[java] view plain copy

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

测试代码的输出:

Current State:0
nothing
start Fan
start Cool
stop Cool
stop Fan
start Fan

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

[java] view plain copy

  1. 例程 4 6 enum State
  2. enum State0{
  3. OFF{
  4. @Override void power(){
  5. }
  6. @Override void power(){
  7. }
  8. },FANONLY{
  9. },
  10. COOL{ };
  11. public abstract void power();
  12. public abstract void cool();
  13. }

(本来是应该将State1作为Aircon1的内部类的。放在外边,power()等需要添加参数Aircon1,变为power(Aircon1 ac)).

现在,丰富有限状态机的细节,增添④动作(action),如事件(event)相应的动作和状态的动作。

为此,在enum State1中,除了状态模式 提取的接口外,添加了状态机的各种动作/action methode
    void entry(Aircon1 ac){pln("→"+ac.state.name());}
    void exit(Aircon1 ac){p(ac.state.name()+"→ ");}
    void startCool(){        p("start Cool");    }
    void stopCool(){        p("stop Cool");    }
    void startFan(){        p("start Fan");    }
    void stopFan(){        p("stop Fan");    }

每个power(Aircon1 ac)、cool(Aircon1 ac)的方法体结构都是:

this.exit(ac);
            //如果有的话,事件(event)相应的动作,如stopFan();
            ac.state =OFF; //下一个状态
            ac.state.entry(ac);

[java] view plain copy

  1. package property.state.stateMachine;
  2. import static tool.Print.*;//pln
  3. /**
  4. * 本来是应该将State1作为Aircon1的内部类的。现在放在外边,
  5. * power()等需要变为power(Aircon1 ac)
  6. */
  7. public enum State1{
  8. OFF{
  9. @Override void exit(Aircon1 ac){super.exit(ac);startFan();}
  10. @Override void power(Aircon1 ac){
  11. this.exit(ac);
  12. ac.state =FANONLY;
  13. ac.state.entry(ac);
  14. }
  15. @Override void cool(Aircon1 ac){
  16. pln("nothing");
  17. }
  18. },FANONLY{
  19. @Override void power(Aircon1 ac){
  20. this.exit(ac);
  21. stopFan();
  22. ac.state =OFF;
  23. ac.state.entry(ac);
  24. }
  25. @Override void cool(Aircon1 ac){
  26. this.exit(ac);
  27. ac.state =COOL;
  28. ac.state.entry(ac);
  29. }
  30. },
  31. COOL{
  32. @Override void exit(Aircon1 ac){super.exit(ac);stopCool();}
  33. @Override void entry(Aircon1 ac){startCool();super.entry(ac);}
  34. @Override void power(Aircon1 ac){
  35. this.exit(ac);
  36. stopFan();
  37. ac.state =OFF;
  38. ac.state.entry(ac);
  39. }
  40. @Override void cool(Aircon1 ac){
  41. this.exit(ac);
  42. ac.state =FANONLY;
  43. ac.state.entry(ac);
  44. }
  45. };
  46. //状态模式 提取的接口
  47. abstract void power(Aircon1 ac);
  48. abstract void cool(Aircon1 ac);
  49. //状态机的各种动作action methode
  50. void entry(Aircon1 ac){pln("→"+ac.state.name());}
  51. void exit(Aircon1 ac){p(ac.state.name()+"→ ");}
  52. void startCool(){        p("start Cool");    }
  53. void stopCool(){        p("stop Cool");    }
  54. void startFan(){        p("start Fan");    }
  55. void stopFan(){        p("stop Fan");    }
  56. }

空调Aircon1的修改版本。

[java] view plain copy

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

对应测试操作的输出:“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

时间: 2024-11-05 16:37:48

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

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

本文从简单的样例入手,逐步演变成很复杂的程序. 在简明 状态模式(5.8)中,状态之间的变换由外界控制,或者说.多种状态是切割的.无关的.状态模式最有趣的地方正是讨论其状态的变迁. 1.引子 空调(air-condition)的遥控器有两个button(很多其它的button在后面的样例中引入),power/电源键和cool/制冷键. 空调的执行呈现3个状态.停止/Off.仅送风/FanOnly.制冷/Cool.起始状态为Off,状态变化图例如以下所看到的. 这是简化的有限状态机(Finite

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

C:\0workspace\AtiPlatf_cms\src\com\attilax\fsm\JavaExpFsm.java String code = "new(com.attilax.util.connReduceDync).set_resfile(uc_js.txt).joinNout() " .trim(); $code=new(com.attilax.user.AgentService).login(admin,admin) [ "new", "

2016最新Java学习计划

一.Java学习路线图 二.Java学习路线图--视频篇 六大阶段 学完后目标 知识点 配套免费资源(视频+笔 记+源码+模板) 密码        第一阶段 Java基础 入门 学习周期: 35天 学完后目标: 1.可进行小型应用程序开发 2.对数据库进行基本的增删改查管理 市场价值:¥5000 计算机基础知识 计算机基础.DOS常用命令.Java概述.JDK环境安装配置.环境变量配置.Java程序入门 1.2015年Java基础视频-深入浅出精华版(强烈推荐) 2.历经5年锤炼(适合初学者入

Java学习第5天

---恢复内容开始--- 今天是2016年5月4号,今天是学习JAVA学习的第5天!今天的主要学习任务是对二维数组的学习. P96 3.7.5 二维数组 动态初始化 数据类型 数组名称 [][]=new 数据类型[行数][列数]   ; 如,int a[][]=new int[7][8]; 静态初始化 数据类型 数组名称 [][]=new 数据类型 [][]{ {值,值,...},{值,值,...},...}; 如,int a[][]=new int[][]{ {1,2,3},{54,6},{8

Java学习-008-判断文件类型实例

此文源码主要为应用 Java 如何判断文件类型的源码及其测试源码.若有不足之处,敬请大神指正,不胜感激!源代码测试通过日期为:2015-2-2 23:02:00,请知悉. Java 判断文件类型源码如下所示: 1 /** 2 * @function 判断文件类型 3 * 4 * @author Aaron.ffp 5 * @version V1.0.0: autoUISelenium main.java.aaron.java.tools FileUtils.java assertFileType

疯狂JAVA学习计划

? Java_StudyPlane ?2015/2/20 ????????大年初二 ????????雨天 1.5小时为1个课时. JAVA学习进度表

java学习教程之代码块

学编程吧java学习教程之代码块发布了,欢迎通过xuebiancheng8.com来访问 java中的代码块包括下面几种: 1.普通代码块 2.构造代码块 3.静态代码块 1.普通代码块很简单看下面这个例子: public class Test{ public static void main(String args[]){ { //此处就是普通代码块,普通代码块中的代码按顺序执行 System.out.println("hello"); } } } 2.构造代码块 public cl

Java学习作业(14.4.21)

前三次作业都是基础语法.真的好水啊.从这次开始记录. 1.编写Java程序,把当前目录下扩展名为txt的文件的扩展名全部更名为back. 1 import java.io.*; 2 import java.lang.*; 3 4 5 public class Home { 6 7 public void reName(String path, String from, String to) { 8 File f = new File(path); //声明File对象,用于导入修改路径 9 Fi

【分享】不知道怎么学java?java学习路线送上!让你不再迷茫!

学习Java之前,先别急,静下心来好好想想:1)你对学习Java是否有兴趣?2)你是否能静下心来坚持不懈地学习?嗯,这是个容易但又绝对不应该忽略的问题,你确信自己对Java感兴趣.而且又有吃苦的准备,那你才可能学好Java!如果具备这两点条件,就请继续往下看(帖子后面我会分享一些java学习教程)Java体系涉及到三个方面:J2SE,J2EE,J2ME(KJAVA).(1)J2SE--Java 2 Platform Standard Edition,即JDK,它是三者的基础,属于桌面级应用开发: