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

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

1.引子

空调(air-condition)的遥控器有两个button(很多其它的button在后面的样例中引入),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还是喜欢分支语句,简洁明快。

例程 4-5 简洁明快
package property.state.stateMachine;
import static tool.Print.*;//pln
/**
* 空调Aircon。简单的模型:
* 遥控器有两个button(很多其它的button在以下的样例中引入),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编写状态类层次。其结构例如以下:

例程 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);

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的改动版本号。

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(不好搞类层次)时,使用责任链吧。

楼主绘图中、考虑很多其它button中....

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

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

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

  2. cocos2d-x 游戏开发之有限状态机(FSM) (四)

    cocos2d-x 游戏开发之有限状态机(FSM) (四) 虽然我们了解了FSM,并且可以写自己的FSM,但是有更好的工具帮我们完成这个繁琐的工作.SMC(http://smc.sourceforge ...

  3. Atitit. 有限状态机 fsm 状态模式

    Atitit. 有限状态机 fsm 状态模式 1. 有限状态机 1 2. "状态表"和"状态轮换表" 1 3. 有限状态机概念(状态(State)事件(Even ...

  4. 有限状态机FSM(自动售报机Verilog实现)

    有限状态机FSM(自动售报机Verilog实现) FSM 状态机就是一种能够描述具有逻辑顺序和时序顺序事件的方法. 状态机有两大类:Mealy型和Moore型. Moore型状态机的输出只与当前状态有 ...

  5. cocos2d-x 游戏开发之有限状态机(FSM) (三)

    cocos2d-x 游戏开发之有限状态机(FSM) (三) 有限状态机简称FSM,现在我们创建一个专门的FSM类,负责管理对象(Monkey)的状态.然后Monkey类就实现了行为与状态分离.Monk ...

  6. cocos2d-x 游戏开发之有限状态机(FSM) (一)

    cocos2d-x 游戏开发之有限状态机(FSM) (一) 参考:http://blog.csdn.net/mgphuang/article/details/5845252<Cocos2d-x游 ...

  7. cocos2d-x 游戏开发之有限状态机(FSM) (二)

    cocos2d-x 游戏开发之有限状态机(FSM)  (二) 1 状态模式

  8. 有限状态机FSM

    有限状态机(Finite-state machine)又称有限状态自动机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型.常用与:正则表达式引擎,编译器的词法和语法分析,游戏设计,网络 ...

  9. [原创][FPGA]有限状态机FSM学习笔记(一)

    1. 概述--何为有限状态机FSM? 有限状态机-Finite State Machine,简写为FSM,是表示有限个状态及在这些状态之间的转移和动作等行为的数学模型,在计算机领域有着广泛的应用.通常 ...

随机推荐

  1. 如何生动形象、切中要点地讲解 OSI 七层模型和两主机传输过程

    作者:繁星亮与鲍包包链接:https://www.zhihu.com/question/24002080/answer/31817536来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转 ...

  2. 进入Linux救援(rescue)模式的四大法门

    原文:http://blog.51cto.com/xxrenzhe/1272838 适用场景: 当误操作修改系统启动文件/etc/fstab, /etc/rc.d/rc.sysinit时,就会造成系统 ...

  3. css按钮口诀 - CSS BUG顺口溜

    在进行CSS网页布局时遇到BUG,请认真阅读以下内容,非常容易记忆的,不知道哪位高人把CSS BUG编成了顺口溜了!看看好不好记住呢? 一.IE边框若显若无,须注意,定是高度设置已忘记: 二.浮动产生 ...

  4. C# 多态理解

    封装.继承.多态,面向对象的三大特性,前两项理解相对容易,但要理解多态,特别是深入的了解,对于初学者而言可能就会有一定困难了.我一直认为学习OO的最好方法就是结合实践,封装.继承在实际工作中的应用随处 ...

  5. jquery开发的”天才笨笨碰“游戏

    前段时间湖南卫视的快乐大本营里有一款“天才笨笨碰”游戏非常火.这款游戏主要是考选手的声母联想词语的能力. 小篇在看完这个节目后用jquery制作了“天才笨笨碰”网页游戏.先上效果图: 游戏规则: 1. ...

  6. Android 避免APP启动闪黑屏(Theme和Style)

    前几天Boss就反应说,机器每次启动程序都会闪一下黑屏,这个客户不接受.没办法,只能想想怎么解决,最后找到了下面的方法.闪黑屏的原因主要是我们启动Activity的时候,需要跑完onCreate和on ...

  7. 元组(Tuple)

    元组(Tuple) 笛卡尔积中每一个元素(d1,d2,…,dn)叫作一个n元组(n-tuple)或简称元组. 元组是关系数据库中的基本概念,关系是一张表,表中的每行(即数据库中的每条记录)就是一个元组 ...

  8. python 全局变量的使用

    我尝试使用 类似 C 语言的方式去调用 python 的全局变量,发现不行,后经过 尝试,要使用 global 进行调用 test_num = 0; # 首先声明一个全局变量 def test_fun ...

  9. 淘宝开放平台获取沙箱token

    沙箱环境的文档都是错的,直接使用以下地址: 输入淘宝测试账号: sandbox_c_1    密码: taobao1234 https://login.tbsandbox.com/member/log ...

  10. 【进阶修炼】——改善C#程序质量(9)

    140,使用默认的访问修饰符. 如果不加访问修饰符,成员变量的默认是private的,类默认是internal的.为了明确访问的权限,我倒是建议都加上访问修饰符,这省不了多少代码. 141,不知道该不 ...