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

简明 状态模式(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. zoj 月赛B题(快速判断一个大数是否为素数)

    给出一个64位的大数,如何快速判断其是否为素数 #include<algorithm> #include<cstdio> #include<cstring> #in ...

  2. Delphi中的三目运算函数有哪些?(XE10.2+WIN764)

    相关资料:https://www.cnblogs.com/rogge7/p/6078903.html 问题现象:在做一个判断时突然想到了C++的三目运算,就在想Delphi中一共有几个? 问题处理: ...

  3. C#学习笔记(2)——操作sqlite数据库增删改查

    说明(2017-5-25 10:49:50): 1. app.config文件 Alt+Shift+C创建类,选择“应用程序配置文件”,添加<connectionStrings>,要先打个 ...

  4. ARKit从入门到精通(4)-ARKit全框架API大全

    转载:http://blog.csdn.net/u013263917/article/details/73156679 1.1-ARKit框架简介 1.2-ARAnchor 1.3-ARCamera ...

  5. php implode

    implode() 函数返回由数组元素组合成的字符串. <?php $arr = array('Hello','World!','I','love','Shanghai!'); echo imp ...

  6. java将图片转换成二进制

    package com.oumyye.图片; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; imp ...

  7. quartz定时任务框架的使用以及原理

    quartz定时任务时间设置 这些星号由左到右按顺序代表 :     *    *     *     *    *     *   *                                 ...

  8. 关于python最大递归深度 - 998

    今天LeetCode的时候暴力求解233 问题: 给定一个整数 n,计算所有小于等于 n 的非负数中数字1出现的个数. 例如: 给定 n = 13, 返回 6,因为数字1出现在下数中出现:1,10,1 ...

  9. AT91SAM9260EK-38k产生原理

    9260内部有5个内部计数器,分别为TIMER_CLOCK1 --- TIMER_CLOCK5.通过这5个时钟可以为各种内部设备提供时钟基准. 其中,红外发射38K方波,是通过CLOCK1计数产生. ...

  10. Linxu

    http://www.92csz.com/study/linux/ MySql 乱码  修改 /etc/my.cnf文件 character-set-server=utf8 , 表名不区分大小写:lo ...