Apache Commons SCXML:有限狀態機實現

本文提到有限狀態機(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

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/372400.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/372400.shtml
英文地址,請注明出處:http://en.pswp.cn/news/372400.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

第二十章、分離應用程序邏輯并處理事件

理解委托 委托是對方法的引用。&#xff08;之所以稱為委托&#xff0c;是因為一旦被調用&#xff0c;就將具體的處理“委托”給引用的方法&#xff09; 委托對象引用了方法&#xff0c;和將int賦值給int變量一樣&#xff0c;是將方法引用賦給委托對象。 Processor p new Proc…

pymol怎么做底物口袋表面_怎么從文獻中發掘一篇新文章?

本文來自微信公眾號&#xff1a;X-MOLNews可能你的導師也曾說過這樣的話——盯著Nature、Science級別的文章做&#xff0c;可能最終會中十分的文章&#xff1b;如果盯著十分的文章做&#xff0c;可能最終發出來也就五六分&#xff1b;但如果就為了發個文章混畢業&#xff0c;很…

如何分析線程轉儲– IBM VM

本文是我們的線程轉儲分析系列的第4部分&#xff0c;它將為您概述什么是IBM VM的JVM線程轉儲以及您將找到的不同線程和數據點。 您將看到和學習??到&#xff0c;IBM VM Thread Dump格式是不同的&#xff0c;但是提供了更多現成的故障排除數據。 在這一點上&#xff0c;您應該…

VMware vSphere克隆虛擬機

參考資料&#xff1a;http://blog.csdn.net/shen_jz2012/article/details/484167711. 首先將你所要克隆的虛擬機關掉2. 選擇你的ESXI服務器選中"配置"&#xff0c;然后選中存儲器右鍵你的存儲介質&#xff0c;比如我的是datastore1&#xff0c;選擇“瀏覽數據存儲”。…

將本地jar包倒入maven項目類庫中

有兩種方法&#xff1a;1.本地下載maven并配置環境變量&#xff0c;然后運行cmd控制臺輸入 mvn install:install-file -Dfile本地jar路徑 -DgroupId -DartifactId -Dpackagingjar -Dversion -DgeneratePomtrue. 2.直接在pom.xml中對應的依賴下面添加<scope>system&l…

Spring和JSF集成:分頁

處理大型數據集時&#xff0c;通常需要以分頁格式顯示數據。 分頁是一個有趣的問題&#xff0c;因為它傾向于跨越應用程序的所有層&#xff0c;從視圖層通過應用程序服務一直到對數據庫的原始調用。 在獲取分頁數據時&#xff0c;有一些非常好的解決方案。 如果您使用的是JPA&a…

三重積分平均值_直角坐標系下的三重積分的幾何可視化解釋圖解高等數學

12.4 直角坐標系下的三重積分三重積分假設 F(x,y,z) 為一個空間有界閉區域 D 上的函數. D 為下面立體橢球所占區域. 將空間區域分割成小長方塊. 體積記為 ΔVk, 其長寬高分別為Δxk, Δyk, Δzk , 并有下列的求和式:觀察下面動畫, 當空間不斷分割, 每個小方塊的體積 ΔVk 不斷變…

最短網絡Agri-Net

【例4-11】、最短網絡Agri-Net【問題描述】農民約翰被選為他們鎮的鎮長&#xff01;他其中一個競選承諾就是在鎮上建立起互聯網&#xff0c;并連接到所有的農場。當然&#xff0c;他需要你的幫助。約翰已經給他的農場安排了一條高速的網絡線路&#xff0c;他想把這條線路共享給…

cors-synchronous-requests-not-working-in-firefox

http://stackoverflow.com/questions/16668386/cors-synchronous-requests-not-working-in-firefox轉載于:https://www.cnblogs.com/diyunpeng/p/5829594.html

硬盤接口協議

硬盤是電腦主要的存儲媒介之一&#xff0c;由一個或者多個鋁制或者玻璃制的碟片組成。碟片外覆蓋有鐵磁性材料。硬盤有固態硬盤&#xff08;SSD 盤&#xff0c;新式硬盤&#xff09;、機械硬盤&#xff08;HDD 傳統硬盤&#xff09;、混合硬盤&#xff08;HHD 一塊基于傳統機械…

圖的表示

Python 數據結構與算法——圖&#xff08;Graph&#xff09; 1. 鄰接矩陣 vs 鄰接表&#xff08;壓縮的鄰接矩陣&#xff09; 鄰接矩陣的缺點是&#xff1a; 空間占用與結點數的平方成正比&#xff0c;可能帶來很大的浪費&#xff1b;鄰接矩陣不容易增加新的結點&#xff0c;不…

在Java Web應用程序中阻止CSRF

跨站點請求偽造攻擊&#xff08;CSRF&#xff09;在Web應用程序中非常常見&#xff0c;如果允許&#xff0c;可能會造成重大危害。 如果您從未聽說過CSRF&#xff0c;建議您查看有關它的OWASP頁面 。 幸運的是&#xff0c;阻止CSRF攻擊非常簡單&#xff0c;我將向您展示它們的工…

windows命令行無法啟動redis_windows系統安裝redis

1、下載最新redis https://github.com/MicrosoftArchive/redis/releases我選擇下載msi版本的2.雙擊下載包安裝3.設置redis環境變量&#xff0c;把redis路徑配置到系統變量path值中4啟動redis&#xff0c;cmd進入安裝好redis文件夾 輸入&#xff1a;如果redis啟動出錯Creating S…

SQL Server 篩選時間區間

一、SQL直接判斷 select * from login where pass>2013/03/25 and pass < 2017/04/24 二、DATEDIFF() 函數返回兩個日期之間的時間 --語法 DATEDIFF(datepart,startdate,enddate) --開始時間 startdate --結束時間 enddate --datepart datepart縮寫年yy, yyyy季度qq, …

OpenShift Express Web管理控制臺:入門

本周&#xff0c; 最新版本的OpenShift為已經很棒的PaaS Cloud提供商帶來了兩個非常好的功能。 首先&#xff0c;JBoss AS已從7.0升級到7.1&#xff0c;并且所有新的Express Web Management Console已作為預覽發布。 在本文中&#xff0c;我們將研究如何使用此新控制臺&#xf…

Linux-IP地址后邊加個/8(16,24,32)是什么意思?

是掩碼的位數 A類IP地址的默認子網掩碼為255.0.0.0&#xff08;由于255相當于二進制的8位1&#xff0c;所以也縮寫成“/8”&#xff0c;表示網絡號占了8位&#xff09;; B類的為255.255.0.0&#xff08;/16&#xff09;; C類的為255.255.255.0(/24) /30就是255…

女士細線毛衣起多少針_從起針到縫合,教你織毛衣的各種要點(詳細教程)

新手學織毛衣看過來&#xff0c;7大編織要點幫你解決織好一件毛衣的基礎問題&#xff0c;滿滿的干貨&#xff0c;每點都值得學習!一、起針二、棒針符號三、如何織小樣四、依據小樣推算針數收掛肩的推算五、斜肩針數的推算開前、后領的位置與針數六、袖山的推算七、如何上袖子一…

關于OPENSSL的使用

#import <Foundation/Foundation.h> interface RSAEncryptor : NSObject /** * 加密方法 * * param str 需要加密的字符串 * param path .der格式的公鑰文件路徑 */ (NSString *)encryptString:(NSString *)str publicKeyWithContentsOfFile:(NSString *)path; /*…

Jelastic Java云端平臺

誰在Jelastic背后&#xff1f; 那是我的第一個問題&#xff0c;因此我瀏覽了Jelastic網站。 回答此問題的最佳方法是查看“ Jelastic團隊”部分。 創始人&#xff0c;顧問&#xff0c;特殊合作伙伴構成了一支真正的專業團隊。 作為特殊的合作伙伴&#xff0c;您會發現MySQL&am…

請先設置tkk_攪拌站水泥罐倉頂除塵器設置及調整

攪拌站水泥罐倉頂除塵器采用脈沖噴吹清灰系統&#xff0c;除塵器本體結構&#xff0c;采用標準模板焊接&#xff0c;整體結構&#xff0c;強度牢靠&#xff0c;組裝維修方便&#xff0c;脈沖清灰采用時序控制器MCY系列?控制閥門KEK系列&#xff0c;噴吹清灰頻率及噴吹間隔可手…