有限状态机(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语言,只要生成的编译文件能匹 ...
随机推荐
- Http请求中Content-Type讲解以及在Spring MVC注解中produce和consumes配置详解
原文地址: https://blog.csdn.net/shinebar/article/details/54408020 引言: 在Http请求中,我们每天都在使用Content-type来指定不 ...
- NIO中的heap Buffer和direct Buffer区别
在Java的NIO中,我们一般采用ByteBuffer缓冲区来传输数据,一般情况下我们创建Buffer对象是通过ByteBuffer的两个静态方法: ByteBuffer.allocate(int c ...
- Win2008建立域时administrator账户密码不符合要求
在win2008中建立域时,有时会出现administrator账户密码不符合要求的现象,报错会说明目前本地administrator账户不需要密码.这是什么原因造成的呢?原来,目前的2008镜像在网 ...
- CListCtrl 之右键菜单
在使用CListCtrl时要为它添加一个右键菜单,步骤如下: 1. 响应CListCtrl的NM_RCLICK消息. 2. 添加一个菜单资源,在菜单资源中插入要添加到菜单内容. 一般存在两种方法: ...
- [leetcode]Subsets @ Python
原题地址:https://oj.leetcode.com/problems/subsets/ 题意:枚举所有子集. 解题思路:碰到这种问题,一律dfs. 代码: class Solution: # @ ...
- iOS开发-16进制颜色转换
项目中经常会用到颜色转换,有的是通过十六进制转成数字转颜色,想简单的点直接通过字符串转一下,简单扩展了一下分类UIColor,代码如下: +(UIColor *)colorWithHex:(NSStr ...
- 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 ...
- Java奇淫巧技之Lombok
http://blog.csdn.net/ghsau/article/details/52334762
- GDB 程序调试简单实践
用了好久的GCC/G++ 却一直都没用过GDB调试过程序,有时程序不是非常大,一般有错,直接看编译器编译结果就几乎相同知道错在哪儿了,或者使用codeblocks单步调试,甚至回到windows以下调 ...
- Swift编程语言学习1.7——断言
断言 可选能够让你推断值是否存在,你能够在代码中优雅地处理值缺失的情况.然而,在某些情况下,假设值缺失或者值并不满足特定的条件,你的代码可能并不须要继续执行.这时.你能够在你的代码中触发一个断言(as ...