SMC - 状态机代码生成工具
一、介绍
1.1 smc简介
SMC是用java开发的一个状态机软件代码生成工具,SMC支持多种开发语言:C、JavaScript、Python、C++、Lua、Ruby、C#、Objective-C、Scala、Groovy、Perl、TCL、Java、PHP、VB.NET等,而我们需要做的就是完成一个.sm的脚本和拥有这些状态的主体类。
利用有限状态机来控制对象的行为,其原理就是利用多态,常常我们自己写代码,需要很大篇幅,万一需要再加一个或者几个状态,自己维护时就会很麻烦,SMC这个工具可以帮助我们解决这个问题。
SMC可以通过一个配置文件,生成有限状态机所需的所有状态类以及状态机类,同时还包括了所有的状态间的转换逻辑。
1.2 环境准备
我们这里以java语言为例来进行说明。
使用这个工具之前我们需要jdk环境,最新版的SMC支持jdk1.7,之前版本的SMC支持jdk1.6,要想中间没有问题,一定要将电脑上的jdk版本与SMC的jdk版本对应起来。
smc下载地址: http://sourceforge.net/projects/smc/files/.
二、 smc文件格式说明
%class 状态机所作用的类
%package 类所在的包
%access 生成类的可访问级别
%start 指定状态机的开始状态
%map 状态机的名字
%%...%%:这一对%%中间定义了各个状态类以及状态的各种行为。格式说明如下:
Start --状态1(名称可自定义)
{
DoStart --Do状态名:执行状态1
State2–执行完状态1之后,跳转到该状态(状态2)
{method1();}–执行状态1时,需要实现的功能
}
State2-状态2
{
DoState2
[ctxt.isSuccessState2()== true] – ctxt:上下文,实体类CoreSchMatch 中isSuccessState2()函数返回值为true时,执行该功能
State3
{
notifyClientState2Ok();
}
DoState2
[ctxt.isSuccessState2()==== false] – ctxt:上下文,实体类CoreSchMatch 中isSuccessState2()函数返回值为false时,执行该功能
State2Fail{notifyClientState2Fail();}
}
State3
{
DoState3
nil{method3();releaseStm();}–表示清空资源;nli-结束状态
}
State2Fail
{
DoState2Fail
nil{releaseStm();}–表示清空资源;nli-结束状态
}
Default –自带状态,加载上面定义的所有动作
{
DoStart
nil
{}
DoState2
nil
{}
DoState3
nil
{}
DoState2Fail
nil
{}
}
三、java - smc 代码生成过程
3.1 java环境
1、创建java工程;
2、引入jar包:Smc.jar
3、创建:SchMatchState.sm文件
3.2 编写smc文件
实现这个状态机的.sm脚本我们将它命名为SchMatchState.sm,
具体的脚本如下所示:
%{
%}
%class SchMatchState
%package com.math.sch
%start SchMatchStateMap::Start
%map SchMatchStateMap
%%
Start
{
DoStart
Busy{state2Busy();}
}
Busy
{
DoBusy [ctxt.isSpecialState() == true] Idle{idleProcess();}
DoBusy [ctxt.isSpecialState() == false] Stop{stopProcess();}
}
Idle{
DoIdle
nil {release();}
}
Stop{
DoStop
nil {release();}
}
Default
{
DoStart
nil
{}
DoBusy
nil
{}
DoIdle
nil
{}
DoStop
nil
{}
}
%%
3.3 写批处理文件:runsmsch.bat
1、创建文件:runsmsch.bat
文件内容:
java -jar Smc.jar -java -g -d ./ 需要处理的状态机.sm文件名
示例:
java -jar Smc.jar -java -g -d ./ SchMatchState.sm
2、执行runsmsch.bat命令:
(1)Window+R,打开cmd命令行窗口;
(2)在命令行中进入smc.jar包的位置:
(3)执行runsmsch.bat文件中命令:
执行过程:
3、执行之后,程序会自动创建SchMatchStateContext类,类中定义状态机的全过程。
4、 SchMatchState类中会自动创建状态机中定义的所有功能函数,根据实际需要实现对应的功能即可。
5、 在SchMatchState类中实现startCoreSchMatch()函数,用于状态机启动 --> 执行所有的动作函数:
public void startCoreSchMatch(){
fsm.enterStartState();
fsm.DoStart();
fsm.DoBusy();
fsm.DoIdle();
fsm.DoStop();
}
3.4 java代码
3.4.1 SchMatchState类
package com.math.sch;
public class SchMatchState {
private SchMatchStateContext fsm;
private String currentState = "start";
public static void main(String[] args) {
new SchMatchState().start();
}
public void start(){
System.out.println("状态机开始: ");
this.fsm = new SchMatchStateContext(this);
startCoreSchMatch();
}
public void startCoreSchMatch(){
fsm.enterStartState();
fsm.DoStart();
fsm.DoBusy();
fsm.DoIdle();
fsm.DoStop();
}
public void state2Busy() {
this.currentState = "busy";
System.out.println("当前状态:"+currentState+" -> 转换状态至:busy");
}
public boolean isSpecialState() {
if("busy".equals(currentState)){
this.currentState = "Special";
return true;
}
return false;
}
public void idleProcess() {
System.out.println("当前状态:"+currentState+" -> 转换状态至:idle");
this.currentState = "stop";
}
public void stopProcess() {
this.currentState = "stop";
System.out.println("当前状态:"+currentState);
}
public void release() {
this.currentState = "start";
System.out.println("状态机结束并清空");
}
}
执行结果输出情况:
3.4.2 SchMatchStateContext类
/*
* ex: set ro:
* DO NOT EDIT.
* generated by smc (http://smc.sourceforge.net/)
* from file : SchMatchState.sm
*/
package com.math.sch;
import java.io.PrintStream;
public class SchMatchStateContext
extends statemap.FSMContext
{
//---------------------------------------------------------------
// Member methods.
//
public SchMatchStateContext(SchMatchState owner)
{
super (SchMatchStateMap.Start);
_owner = owner;
}
public SchMatchStateContext(SchMatchState owner, SchMatchStateState initState)
{
super (initState);
_owner = owner;
}
public void enterStartState()
{
getState().Entry(this);
return;
}
public void DoBusy()
{
_transition = "DoBusy";
getState().DoBusy(this);
_transition = "";
return;
}
public void DoIdle()
{
_transition = "DoIdle";
getState().DoIdle(this);
_transition = "";
return;
}
public void DoStart()
{
_transition = "DoStart";
getState().DoStart(this);
_transition = "";
return;
}
public void DoStop()
{
_transition = "DoStop";
getState().DoStop(this);
_transition = "";
return;
}
public SchMatchStateState getState()
throws statemap.StateUndefinedException
{
if (_state == null)
{
throw(
new statemap.StateUndefinedException());
}
return ((SchMatchStateState) _state);
}
protected SchMatchState getOwner()
{
return (_owner);
}
public void setOwner(SchMatchState owner)
{
if (owner == null)
{
throw (
new NullPointerException(
"null owner"));
}
else
{
_owner = owner;
}
return;
}
//---------------------------------------------------------------
// Member data.
//
transient private SchMatchState _owner;
//---------------------------------------------------------------
// Inner classes.
//
public static abstract class SchMatchStateState
extends statemap.State
{
//-----------------------------------------------------------
// Member methods.
//
protected SchMatchStateState(String name, int id)
{
super (name, id);
}
protected void Entry(SchMatchStateContext context) {}
protected void Exit(SchMatchStateContext context) {}
protected void DoBusy(SchMatchStateContext context)
{
Default(context);
}
protected void DoIdle(SchMatchStateContext context)
{
Default(context);
}
protected void DoStart(SchMatchStateContext context)
{
Default(context);
}
protected void DoStop(SchMatchStateContext context)
{
Default(context);
}
protected void Default(SchMatchStateContext context)
{
if (context.getDebugFlag() == true)
{
PrintStream str =
context.getDebugStream();
str.println(
"TRANSITION : Default");
}
throw (
new statemap.TransitionUndefinedException(
"State: " +
context.getState().getName() +
", Transition: " +
context.getTransition()));
}
//-----------------------------------------------------------
// Member data.
//
}
/* package */ static abstract class SchMatchStateMap
{
//-----------------------------------------------------------
// Member methods.
//
//-----------------------------------------------------------
// Member data.
//
//-------------------------------------------------------
// Constants.
//
public static final SchMatchStateMap_Default.SchMatchStateMap_Start Start =
new SchMatchStateMap_Default.SchMatchStateMap_Start("SchMatchStateMap.Start", 0);
public static final SchMatchStateMap_Default.SchMatchStateMap_Busy Busy =
new SchMatchStateMap_Default.SchMatchStateMap_Busy("SchMatchStateMap.Busy", 1);
public static final SchMatchStateMap_Default.SchMatchStateMap_Idle Idle =
new SchMatchStateMap_Default.SchMatchStateMap_Idle("SchMatchStateMap.Idle", 2);
public static final SchMatchStateMap_Default.SchMatchStateMap_Stop Stop =
new SchMatchStateMap_Default.SchMatchStateMap_Stop("SchMatchStateMap.Stop", 3);
private static final SchMatchStateMap_Default Default =
new SchMatchStateMap_Default("SchMatchStateMap.Default", -1);
}
protected static class SchMatchStateMap_Default
extends SchMatchStateState
{
//-----------------------------------------------------------
// Member methods.
//
protected SchMatchStateMap_Default(String name, int id)
{
super (name, id);
}
protected void DoStart(SchMatchStateContext context)
{
if (context.getDebugFlag() == true)
{
PrintStream str = context.getDebugStream();
str.println("TRANSITION : SchMatchStateMap.Default.DoStart()");
}
return;
}
protected void DoBusy(SchMatchStateContext context)
{
if (context.getDebugFlag() == true)
{
PrintStream str = context.getDebugStream();
str.println("TRANSITION : SchMatchStateMap.Default.DoBusy()");
}
return;
}
protected void DoIdle(SchMatchStateContext context)
{
if (context.getDebugFlag() == true)
{
PrintStream str = context.getDebugStream();
str.println("TRANSITION : SchMatchStateMap.Default.DoIdle()");
}
return;
}
protected void DoStop(SchMatchStateContext context)
{
if (context.getDebugFlag() == true)
{
PrintStream str = context.getDebugStream();
str.println("TRANSITION : SchMatchStateMap.Default.DoStop()");
}
return;
}
//-----------------------------------------------------------
// Inner classse.
//
private static final class SchMatchStateMap_Start
extends SchMatchStateMap_Default
{
//-------------------------------------------------------
// Member methods.
//
private SchMatchStateMap_Start(String name, int id)
{
super (name, id);
}
protected void DoStart(SchMatchStateContext context)
{
SchMatchState ctxt = context.getOwner();
if (context.getDebugFlag() == true)
{
PrintStream str = context.getDebugStream();
str.println("TRANSITION : SchMatchStateMap.Start.DoStart()");
}
(context.getState()).Exit(context);
context.clearState();
try
{
ctxt.state2Busy();
}
finally
{
context.setState(SchMatchStateMap.Busy);
(context.getState()).Entry(context);
}
return;
}
//-------------------------------------------------------
// Member data.
//
}
private static final class SchMatchStateMap_Busy
extends SchMatchStateMap_Default
{
//-------------------------------------------------------
// Member methods.
//
private SchMatchStateMap_Busy(String name, int id)
{
super (name, id);
}
protected void DoBusy(SchMatchStateContext context)
{
SchMatchState ctxt = context.getOwner();
if (context.getDebugFlag() == true)
{
PrintStream str = context.getDebugStream();
str.println("TRANSITION : SchMatchStateMap.Busy.DoBusy()");
}
if (ctxt.isSpecialState() == true)
{
(context.getState()).Exit(context);
context.clearState();
try
{
ctxt.idleProcess();
}
finally
{
context.setState(SchMatchStateMap.Idle);
(context.getState()).Entry(context);
}
}
else if (ctxt.isSpecialState() == false)
{
(context.getState()).Exit(context);
context.clearState();
try
{
ctxt.stopProcess();
}
finally
{
context.setState(SchMatchStateMap.Stop);
(context.getState()).Entry(context);
}
} else
{
super.DoBusy(context);
}
return;
}
//-------------------------------------------------------
// Member data.
//
}
private static final class SchMatchStateMap_Idle
extends SchMatchStateMap_Default
{
//-------------------------------------------------------
// Member methods.
//
private SchMatchStateMap_Idle(String name, int id)
{
super (name, id);
}
protected void DoIdle(SchMatchStateContext context)
{
SchMatchState ctxt = context.getOwner();
if (context.getDebugFlag() == true)
{
PrintStream str = context.getDebugStream();
str.println("TRANSITION : SchMatchStateMap.Idle.DoIdle()");
}
SchMatchStateState endState = context.getState();
context.clearState();
try
{
ctxt.release();
}
finally
{
context.setState(endState);
}
return;
}
//-------------------------------------------------------
// Member data.
//
}
private static final class SchMatchStateMap_Stop
extends SchMatchStateMap_Default
{
//-------------------------------------------------------
// Member methods.
//
private SchMatchStateMap_Stop(String name, int id)
{
super (name, id);
}
protected void DoStop(SchMatchStateContext context)
{
SchMatchState ctxt = context.getOwner();
if (context.getDebugFlag() == true)
{
PrintStream str = context.getDebugStream();
str.println("TRANSITION : SchMatchStateMap.Stop.DoStop()");
}
SchMatchStateState endState = context.getState();
context.clearState();
try
{
ctxt.release();
}
finally
{
context.setState(endState);
}
return;
}
//-------------------------------------------------------
// Member data.
//
}
//-----------------------------------------------------------
// Member data.
//
}
}
/*
* Local variables:
* buffer-read-only: t
* End:
*/