Apache Commons SCXML:有限状态机实现
本文提到有限狀態(tài)機(jī)(FSM),SCXML(狀態(tài)圖可擴(kuò)展標(biāo)記語言)和Apache Common的SCXML庫(kù)。 本文還提供了基本的ATM有限狀態(tài)機(jī)示例代碼。
有限狀態(tài)機(jī):
您可能還記得計(jì)算機(jī)科學(xué)課程中的有限狀態(tài)機(jī)。 FSM用于設(shè)計(jì)計(jì)算機(jī)程序或數(shù)字電路。
有限狀態(tài)機(jī)樣本[2]
FSM只是一種抽象機(jī)器,可以處于有限狀態(tài)中的一種。該機(jī)器一次僅處于一種狀態(tài);
它在任何給定時(shí)間所處的狀態(tài)稱為當(dāng)前狀態(tài)。
當(dāng)由觸發(fā)事件或條件啟動(dòng)時(shí),它可以從一種狀態(tài)更改為另一種狀態(tài),這稱為過渡。
特定的FSM由來自每個(gè)當(dāng)前狀態(tài)的可能過渡狀態(tài)列表以及每個(gè)過渡的觸發(fā)條件定義。
SCXML語言:
可以使用稱為SCXML (用于控制抽象的狀態(tài)機(jī)表示法,由W3C出版)的工作草案來描述復(fù)雜的狀態(tài)機(jī)。 SCXML是基于xml的通用狀態(tài)機(jī)語言。 它仍然是草案,最新版本是2012年2月16日。單擊此處以獲取有關(guān)SCXML文檔的五分鐘介紹。
Apache Commons SCXML庫(kù):
Apache的實(shí)現(xiàn)旨在創(chuàng)建和維護(hù)Java SCXML引擎,該引擎能夠執(zhí)行使用SCXML文檔定義的狀態(tài)機(jī),同時(shí)抽象出環(huán)境接口。 最新的穩(wěn)定版本是0.9。
- 圖書館網(wǎng)站: http : //commons.apache.org/scxml/index.html
- Eclipse插件: http : //commons.apache.org/sandbox/gsoc/2010/scxml-eclipse/ (仍在開發(fā)中)
- 用例: http : //commons.apache.org/scxml/usecases.html
SCXML編輯器:
Apache的Eclipse插件旨在提供一個(gè)可視化編輯器來編輯SCXML文件,但它仍在開發(fā)中。 還有一個(gè)非常成功的scxml gui( http://code.google.com/p/scxmlgui/ )。 您也可以查看State Forge的可視狀態(tài)機(jī)圖: http : //www.stateforge.com/StateMachineDiagram/StateMachineDiagram.html
代碼示例:
在本文的這一部分中,我們將實(shí)現(xiàn)一個(gè)基本的ATM狀態(tài)狀態(tài)機(jī)。 作為簡(jiǎn)要信息,我們假設(shè)ATM可以具有以下狀態(tài)。 :
- 空閑:當(dāng)ATM沒有任何活動(dòng)時(shí),只是將其關(guān)閉
- 加載:當(dāng)空閑的atm嘗試連接到ATM服務(wù)器時(shí),配置和信息開始加載
- 服務(wù)中斷:如果ATM加載失敗或ATM關(guān)閉
- 在服務(wù) :如果ATM老丁是成功或ATM被啟動(dòng)
- 斷開連接:如果ATM未連接到網(wǎng)絡(luò)
很抱歉缺少有關(guān)ATM狀態(tài)的信息。 這只是一個(gè)例子。 首先使用scxmlgui程序繪制狀態(tài)機(jī)。 一個(gè)人可以編寫自己的scxml文件,但是scxmlgui會(huì)為您完成這項(xiàng)艱巨的任務(wù)。 這是描述ATM的狀態(tài)變化的狀態(tài)圖:
以及輸出SCXML文件,該文件描述了上圖中的轉(zhuǎn)換:
<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實(shí)現(xiàn)在AtmStatusFSM類中。
- AtmStatusFSM類擴(kuò)展了org.apache.commons.scxml.env.AbstractStateMachine。
- 通過向超級(jí)構(gòu)造函數(shù)提供scxml文件( atm_status.xml )路徑來配置FSM。
- ATM狀態(tài)更改由事件控制。 當(dāng)使用相關(guān)事件名稱[例如fireEvent('atm.connected')]調(diào)用fireEvent方法時(shí),FSM狀態(tài)將自動(dòng)更新。 您可以隨時(shí)獲取當(dāng)前狀態(tài)。
- 您還可以編寫具有FSM狀態(tài)名稱的公共方法。 當(dāng)相應(yīng)狀態(tài)被激活時(shí),將調(diào)用這些方法。
我們有以下枚舉文件來描述我們的事件。 您不必編寫此類代碼,但這可能有助于定義事件。 您還可以使用getEngine()。getCurrentStatus()。getEvents()代碼片段動(dòng)態(tài)獲取這些事件。
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首先顯示可能觸發(fā)的事件。 選擇并提交事件后,將顯示當(dāng)前的ATM狀態(tài),并更新事件列表。
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;}} 我們的簡(jiǎn)單程序的輸出:
下圖給出了Eclipse中顯示的項(xiàng)目文件(帶有必需的庫(kù)): 有關(guān)完整的源代碼,請(qǐng)?jiān)L問https://github.com/ozkansari/atmstatemachine
參考:來自Java Fun博客的JCG合作伙伴 Ozkan SARI的Apache Commons SCXML輕松有限狀態(tài)機(jī)實(shí)現(xiàn) 。
翻譯自: https://www.javacodegeeks.com/2012/06/apache-commons-scxml-finite-state.html
總結(jié)
以上是生活随笔為你收集整理的Apache Commons SCXML:有限状态机实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在Oracle Coherence中分发
- 下一篇: 在没有XML的情况下测试Spring和H