有限状态机(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 例程 4-5 简洁明快
package property.state.stateMachine;
import static tool.Print.*;//pln
/**
* 空调Aircon。简单的模型:
* 遥控器有两个按钮(更多的按钮在下面的例子中引入),power电源键和cool制冷键。
* 空调的运行呈现3个状态,停止/Off、仅送风/FanOnly、制冷/Cool。
* 起始状态为Off
* @author (yqj2065)
* @version 0.1
*/
public class Aircon0{
// off,FanOnly,AC
private int state=0;//起始状态为Off
public int getState(){return state;}
//两个Action
public void power(){//按power键
if(state==0){//off
state=1;
pln("start Fan");
}else if(state==1){//FanOnly
state=0;
pln("stop Fan");
}else{
state=0;
pln("stop Cool");
}
} public void cool(){//按制冷键
if(state==0){//off
pln("nothing");
}else if(state==1){//FanOnly
state=2;
pln("start Cool");
}else{
state=1;
pln("stop Cool");
}
}
}
package property.state.stateMachine;
public class ACCtrl{
public static void test(){
Aircon0 ac = new Aircon0();//power() cool()
System.out.println("Current State:" + ac.getState());
ac.cool();
ac.power();
ac.cool();
ac.cool();
ac.power();
ac.power();
}
}
测试代码的输出: Current State:0
nothing
start Fan
start Cool
stop Cool
stop Fan
start Fan
在此基础上,可以花10分钟练习一下,采用状态模式修改上述代码。我们使用enum编写状态类层次。其结构如下:
[java] view plain copy
例程 4 6 enum State
enum State0{
OFF{
@Override void power(){
}
@Override void power(){
}
},FANONLY{
},
COOL{ };
public abstract void power();
public abstract void cool();
}
(本来是应该将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
package property.state.stateMachine;
import static tool.Print.*;//pln
/**
* 本来是应该将State1作为Aircon1的内部类的。现在放在外边,
* power()等需要变为power(Aircon1 ac)
*/
public enum State1{
OFF{
@Override void exit(Aircon1 ac){super.exit(ac);startFan();}
@Override void power(Aircon1 ac){
this.exit(ac);
ac.state =FANONLY;
ac.state.entry(ac);
}
@Override void cool(Aircon1 ac){
pln("nothing");
}
},FANONLY{
@Override void power(Aircon1 ac){
this.exit(ac);
stopFan();
ac.state =OFF;
ac.state.entry(ac);
}
@Override void cool(Aircon1 ac){
this.exit(ac);
ac.state =COOL;
ac.state.entry(ac);
}
},
COOL{
@Override void exit(Aircon1 ac){super.exit(ac);stopCool();}
@Override void entry(Aircon1 ac){startCool();super.entry(ac);}
@Override void power(Aircon1 ac){
this.exit(ac);
stopFan();
ac.state =OFF;
ac.state.entry(ac);
}
@Override void cool(Aircon1 ac){
this.exit(ac);
ac.state =FANONLY;
ac.state.entry(ac);
}
};
//状态模式 提取的接口
abstract void power(Aircon1 ac);
abstract void cool(Aircon1 ac);
//状态机的各种动作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"); }
}
空调Aircon1的修改版本。
[java] view plain copy package property.state.stateMachine;
import static tool.Print.*;//pln
/**
* 空调Aircon1。使用状态模式重构Aircon0,使用enum State1编写状态类层次。
* @author (yqj2065)
* @version 0.1
*/
public class Aircon1{
State1 state= State1.OFF;//private改默认,删除getState()。
//两个Action
public void power(){//按power键
state.power(this);
}
public void cool(){//按制冷键
state.cool(this);
}
/**
* ACCtrl的代码。
*/
public static void test(){
Aircon1 ac = new Aircon1();
System.out.println("Current State:" + ac.state.name());
ac.cool();
ac.power();
ac.cool();
ac.cool();
ac.power();
ac.power();
ac.power(); }
}
对应测试操作的输出:“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的更多相关文章
- 有限状态机(FSM)的Java 演示
本文从简单的样例入手,逐步演变成很复杂的程序. 在简明 状态模式(5.8)中,状态之间的变换由外界控制,或者说.多种状态是切割的.无关的.状态模式最有趣的地方正是讨论其状态的变迁. 1.引子 空调(a ...
- Atitit.java expression fsm 表达式词法分析引擎 v2 qaa.docx
Atitit.java expression fsm 表达式词法分析引擎 v2 qaa.docx C:\0workspace\AtiPlatf_cms\src\com\attilax\fsm\Java ...
- Atitit.java expression fsm 表达式分词fsm引擎
Atitit.java expression fsm 表达式分词fsm引擎 C:\0workspace\AtiPlatf_cms\src\com\attilax\fsm\JavaExpFsm.java ...
- 0037 Java学习笔记-多线程-同步代码块、同步方法、同步锁
什么是同步 在上一篇0036 Java学习笔记-多线程-创建线程的三种方式示例代码中,实现Runnable创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ...
- 0035 Java学习笔记-注解
什么是注解 注解可以看作类的第6大要素(成员变量.构造器.方法.代码块.内部类) 注解有点像修饰符,可以修饰一些程序要素:类.接口.变量.方法.局部变量等等 注解要和对应的配套工具(APT:Annot ...
- 分享篇——我的Java学习路线
虽然之前我是开发出身,但是我学习的语言是Objective-c,这个语言使用起来范围比较窄,对于自动化学习来说也是无用武之地,所以我自己学习了Java,对于一个有开发经验的人来说学习一门新语言相对来说 ...
- Java学习笔记(04)
Java学习笔记(04) 如有不对或不足的地方,请给出建议,谢谢! 一.对象 面向对象的核心:找合适的对象做合适的事情 面向对象的编程思想:尽可能的用计算机语言来描述现实生活中的事物 面向对象:侧重于 ...
- Java学习心得之 HttpClient的GET和POST请求
作者:枫雪庭 出处:http://www.cnblogs.com/FengXueTing-px/ 欢迎转载 Java学习心得之 HttpClient的GET和POST请求 1. 前言2. GET请求3 ...
- 0032 Java学习笔记-类加载机制-初步
JVM虚拟机 Java虚拟机有自己完善的硬件架构(处理器.堆栈.寄存器等)和指令系统 Java虚拟机是一种能运行Java bytecode的虚拟机 JVM并非专属于Java语言,只要生成的编译文件能匹 ...
随机推荐
- iOS:给图片置灰色
一.在iOS开发中,给图片置灰色这个功能经常会用到,例如商品展示时,商品过期或者下线了,那么图片就需要这个功能.下面这个方法就可以到达目的. /** UIImage:去色功能的实现(图片灰色显示) @ ...
- [leetcode]Anagrams @ Python
原题地址:https://oj.leetcode.com/problems/anagrams/ 题意: Given an array of strings, return all groups of ...
- [leetcode]Interleaving String @ Python
原题地址:https://oj.leetcode.com/problems/interleaving-string/ 题意: Given s1, s2, s3, find whether s3 is ...
- [leetcode]Triangle @ Python
原题地址:https://oj.leetcode.com/problems/triangle/ 题意: Given a triangle, find the minimum path sum from ...
- Distinct Subsequences leetcode java
题目: Given a string S and a string T, count the number of distinct subsequences of T in S. A subseque ...
- Wildcard Matching leetcode java
题目: Implement wildcard pattern matching with support for '?' and '*'. '?' Matches any single charact ...
- Ubuntu环境变量解析
在Ubuntu中有如下几个文件可以设置环境变量 /etc/profile:在登录时,操作系统定制用户环境时使用的第一个文件,此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行. /e ...
- tensoflow数据读取
数据读取 TensorFlow程序读取数据一共有3种方法: 供给数据(Feeding): 在TensorFlow程序运行的每一步, 让Python代码来供给数据. 从文件读取数据: 在TensorFl ...
- mac sierra 10.12部分注册机Special-K+CORE Keygen不能运行的问题
自从mac升级到了sierra之后,很多注册机都打不开了,于是,我想尽了很多办法之后,终于搞定. 1.国外的大神,开发了一个软件,可以修复你的破解补丁,操作方法如下: 下载软件 http://bbs. ...
- Virtualbox安装Ubuntu
每次安装虚拟机都是总要折腾一下,毕竟不是特别熟悉,几个小细节总要google半天,为了以后能愉快的玩耍.把这些问题都记录下来,免得再折腾. 此文档都来自其他人的文章,我保存在Evernote整理. 网 ...