本文提到有限状态机(FSM),SCXML(状态图可扩展标记语言)和Apache Common的SCXML库。 本文还提供了基本的ATM有限状态机示例代码。

有限状态机:

您可能还记得计算机科学课程中的有限状态机。 FSM用于设计计算机程序或数字电路。

有限状态机样本[2]

FSM只是一种抽象机器,可以处于有限状态中的一种。该机器一次仅处于一种状态;

它在任何给定时间所处的状态称为当前状态。

当由触发事件或条件启动时,它可以从一种状态更改为另一种状态,这称为过渡。

特定的FSM由来自每个当前状态的可能过渡状态列表以及每个过渡的触发条件定义。

SCXML语言:

可以使用称为SCXML (用于控制抽象的状态机表示法,由W3C出版)的工作草案来描述复杂的状态机。 SCXML是基于xml的通用状态机语言。 它仍然是草案,最新版本是2012年2月16日。单击此处以获取有关SCXML文档的五分钟介绍。

Apache Commons SCXML库:

Apache的实现旨在创建和维护Java SCXML引擎,该引擎能够执行使用SCXML文档定义的状态机,同时抽象出环境接口。 最新的稳定版本是0.9。

  • 图书馆网站: http : //commons.apache.org/scxml/index.html
  • Eclipse插件: http//commons.apache.org/sandbox/gsoc/2010/scxml-eclipse/ (仍在开发中)
  • 用例: http : //commons.apache.org/scxml/usecases.html

SCXML编辑器:

Apache的Eclipse插件旨在提供一个可视化编辑器来编辑SCXML文件,但它仍在开发中。 还有一个非常成功的scxml gui( http://code.google.com/p/scxmlgui/ )。 您也可以查看State Forge的可视状态机图: http : //www.stateforge.com/StateMachineDiagram/StateMachineDiagram.html

代码示例:

在本文的这一部分中,我们将实现一个基本的ATM状态状态机。 作为简要信息,我们假设ATM可以具有以下状态。 :

  • 空闲:当ATM没有任何活动时,只是将其关闭
  • 加载:当空闲的atm尝试连接到ATM服务器时,配置和信息开始加载
  • 服务中断:如果ATM加载失败或ATM关闭
  • 在服务 :如果ATM老丁是成功或ATM被启动
  • 断开连接:如果ATM未连接到网络

很抱歉缺少有关ATM状态的信息。 这只是一个例子。 首先使用scxmlgui程序绘制状态机。 一个人可以编写自己的scxml文件,但是scxmlgui会为您完成这项艰巨的任务。 这是描述ATM的状态变化的状态图:

以及输出SCXML文件,该文件描述了上图中的转换:

<scxml initial="idle" name="atm.connRestored" version="0.9" xmlns="http://www.w3.org/2005/07/scxml"><state id="idle"><transition event="atm.connected" target="loading"></transition></state><state id="loading"><transition event="atm.loadSuccess" target="inService"></transition><transition event="atm.connClosed" target="disconnected"></transition><transition event="atm.loadFail" target="outOfService"></transition></state><state id="inService"><transition event="atm.shutdown" target="outOfService"></transition><transition event="atm.connLost" target="disconnected"></transition></state><state id="outOfService"><transition event="atm.startup" target="inService"></transition><transition event="atm.connLost" target="disconnected"></transition></state><state id="disconnected"><transition event="atm.connRestored" target="inService"></transition></state></scxml>

我们的FSM实现在AtmStatusFSM类中。

  • AtmStatusFSM类扩展了org.apache.commons.scxml.env.AbstractStateMachine。
  • 通过向超级构造函数提供scxml文件( atm_status.xml )路径来配置FSM。
  • ATM状态更改由事件控制。 当使用相关事件名称[例如fireEvent('atm.connected')]调用fireEvent方法时,FSM状态将自动更新。 您可以随时获取当前状态。
  • 您还可以编写具有FSM状态名称的公共方法。 当相应状态被激活时,将调用这些方法。
package net.javafun.example.atmstatusfsm;import java.util.Collection;
import java.util.Set;import org.apache.commons.scxml.env.AbstractStateMachine;
import org.apache.commons.scxml.model.State;/*** Atm Status Finite State Machine* * @see  Apache Commons Scxml Library * @author ozkansari.com**/
public class AtmStatusFSM extends AbstractStateMachine {/*** State Machine uses this scmxml config file*/private static final String SCXML_CONFIG_ATM_STATUS = "net/javafun/example/atmstatusfsm/atm_status.xml";/** CONSTRUCTOR(S) */public AtmStatusFSM() {super(AtmStatusFSM.class.getClassLoader().getResource(SCXML_CONFIG_ATM_STATUS));}/** HELPER METHOD(S) *//*** Fire the event*/public void firePreDefinedEvent(AtmStatusEventEnum eventEnum){System.out.println("EVENT: " + eventEnum);this.fireEvent(eventEnum.getEventName());}public void callState(String name){this.invoke(name);}/*** Get current state ID as string*/public String getCurrentStateId() {Set states = getEngine().getCurrentStatus().getStates();State state = (State) states.iterator().next();return state.getId();}/*** Get current state as apache's State object*/public State getCurrentState() {Set states = getEngine().getCurrentStatus().getStates();return ( (State) states.iterator().next());}/*** Get events belongs to current status of the FSM*/public Collection getCurrentStateEvents() {return getEngine().getCurrentStatus().getEvents();}/** STATES */// Each method below is the activity corresponding to a state in the// SCXML document (see class constructor for pointer to the document).public void idle() {System.out.println("STATE: idle");}public void loading() {System.out.println("STATE: loading");}public void inService() {System.out.println("STATE: inService");}public void outOfService() {System.out.println("STATE: outOfService");}public void disconnected() {System.out.println("STATE: disconnected");}
}

我们有以下枚举文件来描述我们的事件。 您不必编写此类代码,但这可能有助于定义事件。 您还可以使用getEngine()。getCurrentStatus()。getEvents()代码片段动态获取这些事件。

package net.javafun.example.atmstatusfsm;/*** Atm Status Change Events* * @author ozkansari.com**/
public enum AtmStatusEventEnum {CONNECT("atm.connected"), CONNECTION_CLOSED("atm.connClosed"),CONNECTION_LOST("atm.connLost"),CONNECTION_RESTORED("atm.connRestored"),LOAD_SUCCESS("atm.loadSuccess"),LOAD_FAIL("atm.loadFail"),SHUTDOWN("atm.shutdown"),STARTUP("atm.startup");private final String eventName;private AtmStatusEventEnum(String eventName) {this.eventName = eventName;}public String getEventName() {return eventName;}public static String getNamesAsCsv(){StringBuilder sb = new StringBuilder();for (AtmStatusEventEnum e : AtmStatusEventEnum.values()) {sb.append(e.name());sb.append(",");}return sb.substring(0,sb.length()-2);}}

您可以在下面看到基本的GUI代码。 GUI首先显示可能触发的事件。 选择并提交事件后,将显示当前的ATM状态,并更新事件列表。

package net.javafun.example.atmstatusfsm;import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;import org.apache.commons.scxml.model.Transition;/*** Atm Status Change GUI* * @author ozkansari.com**/
public class AtmDisplay extends JFrame implements ActionListener {private static final long serialVersionUID = -5083315372455956151L;private AtmStatusFSM atmStatusFSM;private JButton button;private JLabel state;private JComboBox eventComboBox = new JComboBox();public static void main(String[] args) {new AtmDisplay();}public AtmDisplay() {super("ATM Display Demo");atmStatusFSM = new AtmStatusFSM();setupUI();}@SuppressWarnings("deprecation")private void setupUI() {JPanel panel = new JPanel();panel.setLayout(new BorderLayout());setContentPane(panel);button = makeButton("FIRE_EVENT", AtmStatusEventEnum.getNamesAsCsv(), "Submit" );panel.add(button, BorderLayout.CENTER);state = new JLabel(atmStatusFSM.getCurrentStateId());panel.add(state, BorderLayout.SOUTH);initEvents();panel.add(eventComboBox, BorderLayout.NORTH);pack();setLocation(200, 200);setResizable(false);setSize(300, 125);show();setDefaultCloseOperation(EXIT_ON_CLOSE);}@SuppressWarnings("unchecked")private void initEvents() {eventComboBox.removeAllItems();List transitionList = atmStatusFSM.getCurrentState().getTransitionsList();for (Transition transition : transitionList) {eventComboBox.addItem(transition.getEvent() );}}public void actionPerformed(ActionEvent e) {String command = e.getActionCommand();if(command.equals("FIRE_EVENT")) {checkAndFireEvent();}}private boolean checkAndFireEvent() {atmStatusFSM.fireEvent(eventComboBox.getSelectedItem().toString());state.setText(atmStatusFSM.getCurrentStateId());initEvents();repaint();return true;}private JButton makeButton(final String actionCommand, final String toolTipText, final String altText) {JButton button = new JButton(altText);button.setActionCommand(actionCommand);button.setToolTipText(toolTipText);button.addActionListener(this);button.setOpaque(false);return button;}}

我们的简单程序的输出:

下图给出了Eclipse中显示的项目文件(带有必需的库): 有关完整的源代码,请访问https://github.com/ozkansari/atmstatemachine

参考:来自Java Fun博客的JCG合作伙伴 Ozkan SARI的Apache Commons SCXML轻松有限状态机实现 。

翻译自: https://www.javacodegeeks.com/2012/06/apache-commons-scxml-finite-state.html

Apache Commons SCXML:有限状态机实现相关推荐

  1. java Apache Commons jar包简介

    一.Commons BeanUtils 说明:针对Bean的一个工具集.由于Bean往往是有一堆get和set组成,所以BeanUtils也是在此基础上进行一些包装. 二.Commons CLI 说明 ...

  2. 初识 Apache Commons jar 包

    长篇预警 ,要有耐心才能看下去 1.1. 开篇 在Java的世界,有很多(成千上万)开源的框架,有成功的,也有不那么成功的,有声名显赫的,也有默默无闻的.在我看来,成功而默默无闻的那些框架值得我们格外 ...

  3. 编写更少量的代码:使用apache commons工具类库

    Commons-configuration Commons-FileUploadCommons DbUtilsCommons BeanUtils Commons CLI Commons CodecCo ...

  4. c++解析csv 存入数组_使用Apache Commons CSV在Java中读写CSV

    介绍 这是专门针对Java读写CSV的库的简短系列文章的第二篇,也是上一篇文章" Core Java读写CSV"的直接续篇. Apache Commons CSV 在Apache的 ...

  5. org.apache.commons.lang.StringUtils的jar包是什么

    org.apache.commons.lang.StringUtils的jar包是什么 commons-lang-2.5.jar

  6. 使用Apache Commons Configuration读取配置信息

    2019独角兽企业重金招聘Python工程师标准>>> 在项目中使用一些比较新的库总会给你带来很多快乐,在这篇文章中,我将会给你介绍一个在Java中读取配置文件的框架--Apache ...

  7. Apache commons email 使用过程中遇到的问题

    apache-commons-email是对mail的一个封装,所以使用起来确实是很方便.特别的,官网上的tutorial也是极其的简单.但是我也仍然是遇到了没有解决的问题. jar包的添加 mail ...

  8. Apache Commons包 StringUtils工具类深入整理(转载)

    [转载地址]:cnblogs.com/sealy321/p/10227131.html 字符串是在程序开发中最常见的,Apache Commons开源项目在org.apache.commons.lan ...

  9. Apache Commons Math3学习笔记(2) - 多项式曲线拟合(转)

    多项式曲线拟合:org.apache.commons.math3.fitting.PolynomialCurveFitter类. 用法示例代码: [java] view plain copy   // ...

最新文章

  1. s-sgdisk源码分析 “--set-alignment=value分区对齐参数”
  2. 【c语言】蓝桥杯算法提高 c++_ch02_01
  3. 巴西CC成为FreeStor全球首个用户
  4. mysql数据库varchar的区别_MySQL数据库char与varchar的区别分析及使用建议
  5. hdfs namenode -format 初始化创建不了目录的问题
  6. FFmpeg 音视频同步
  7. 用c语言运行Linux命令,使用execv(C语言)从linux命令提示符运行命令
  8. 查看tensorflow版本以及路径:
  9. C语言怎么样?C语言如何?
  10. 【To Debug】牛客网--华为机试在线训练3:明明的随机数
  11. centos7.6(腾讯云)开放端口及配置腾讯云安全组
  12. 如何提高迅雷下载速度
  13. 书摘---创业36条军规4:如何组建公司
  14. 小程序 打开地图导航
  15. MySql报错1153
  16. mysql多对多关系的理解,由一对多看向多对多
  17. 计算机网络:网间互联协议
  18. 云服务器环境安装、卸载与配置:mysql
  19. day04 RabbitMQ基本使用
  20. 体积最小,极速秒装的APK安装器

热门文章

  1. JVM参数设置、分析(转)
  2. mysql批量插入数据的函数和存储过程
  3. mysql error 1045 的解决方法
  4. swarm 容器_Oracle应用容器云上的WildFly Swarm
  5. jdk 细粒度锁_使用JDK 8轻松进行细粒度排序
  6. java javadoc_使用Java 9向Javadoc搜索添加术语
  7. java更好的语言_五个使Java变得更好的功能
  8. web.xml.jsf_JSF 2.2在30秒内创建一个自定义Hello World组件
  9. swagger api文档_带有Swagger的Spring Rest API –创建文档
  10. hazelcast_Hazelcast的MapLoader陷阱