当前位置:   article > 正文

SMC - 状态机代码生成工具_状态机代码生成器

状态机代码生成器

一、介绍

1.1 smc简介

     smc官网地址: 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 状态机的名字
%%...%%:这一对%%中间定义了各个状态类以及状态的各种行为。格式说明如下:
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

注意:sm文件名称需要与.sm文件中指定的%class 类名称 相同

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 -- 默认状态转换:被放置在一个状态中,用于备份所有转换。
        {
           nil{ process();}
        }
}
Default –默认状态,如果状态机接收到未在该状态机中定义的转换时,定义该状态下的动作或转换
{
    DoStart
        nil
        {}
    DoState2
   		nil
        {}
   DoState3
		nil
	    {}
   DoState2Fail
		nil
	    {}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

三、java - smc 代码生成过程

3.1 java环境

1、创建java工程;
2、引入jar包:Smc.jar
3、创建:SchMatchState.sm文件
1

3.2 编写smc文件

  下面设计这样一个简单状态机,程序初始化时,进入"start"初始状态;当在”"start"初始状态收到信号时,进入”busy“状态;当在"busy"状态收到一个"special"的信号时,进入"idle"状态,当在"busy"状态收到一个"exception"的信号时,进入"stop"退出状态。

实现这个状态机的.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
   		{}
}
%%
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

3.3 执行.sm文件

执行.sm文件,生成对应的类和方法,有两种方法:
1、通过命令行执行生成;
2、通过ant自动化编译工具生成;

3.3.1 命令行方式

1、命令行内容:
java -jar Smc.jar -java -g -d ./ 需要处理的状态机.sm文件名
示例:

java -jar Smc.jar  -java -g -d ./ SchMatchState.sm
  • 1

2、执行命令:
(1)Window+R,打开cmd命令行窗口;
(2)在命令行中进入smc.jar包的位置:
(3)执行命令:

注意:sm文件名称需要与.sm文件中指定的%class 类名称 相同,我这边因为名称不相同导致生成异常:
2

执行过程:
3
3、执行之后,程序会自动创建SchMatchStateContext类,类中定义状态机的全过程。
4
4、 SchMatchState类中会自动创建状态机中定义的所有功能函数,根据实际需要实现对应的功能即可。

  如果没有生成SchMatchState类,可在SchMatchStateContext类中根据提示,依次生成对应的类和函数,并实现对应的函数功能。

5、 在SchMatchState类中实现startCoreSchMatch()函数,用于状态机启动 --> 执行所有的动作函数:

public void startCoreSchMatch(){
		fsm.enterStartState();
		fsm.DoStart();
		fsm.DoBusy();
		fsm.DoIdle();
		fsm.DoStop();
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

3.3.2 通过ant自动化编译工具生成

  Apache Ant 是一个将软件编译、测试、部署等步骤联系在一起加以自动化的一个工具,大多用于Java环境中的软件开发。在实际软件开发中,有很多地方可以用到ant。
  ant的相关介绍和下载可参考链接: Apache Ant的基础使用教程.

3.4 java代码

本文案例的资源链接:SMC - 状态机 - 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("状态机结束并清空");
	}

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

执行结果输出情况:
4

总结:FSM是一种固定的范式,因此采用工具帮我们实现可以减少犯错误的机会。输入的文件就是:实体.sm。我们把重点放在业务逻辑上,所以与状态有关的代码smc都帮我们生成好了。

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:
 */
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • 413
  • 414
  • 415
  • 416
  • 417
  • 418
  • 419
  • 420
  • 421
  • 422
  • 423
  • 424
  • 425
  • 426
  • 427
  • 428
  • 429
  • 430
  • 431
  • 432
  • 433
  • 434
  • 435
  • 436
  • 437
  • 438
  • 439
  • 440
  • 441
  • 442
  • 443
  • 444
  • 445
  • 446
  • 447
  • 448
  • 449
  • 450
  • 451
  • 452
  • 453
  • 454
  • 455
  • 456
  • 457
  • 458
  • 459
  • 460
  • 461
  • 462
  • 463
  • 464
  • 465
  • 466
  • 467
  • 468
  • 469
  • 470
  • 471
  • 472
  • 473
  • 474
  • 475
  • 476
  • 477
  • 478

四、工作流程图生成

  生成sm工作流程图,可以通过图形直观看到当前.sm文件定义的状态及转移过程情况。
详情链接:Graphviz - 生成smc 的.sm文件对应的工作流程图.

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/129913
推荐阅读
相关标签
  

闽ICP备14008679号