Java自动机实现

这篇文章将解决在Java中实现有限状态机的问题。 如果您不知道什么是FSM或在什么地方可以使用FSM,您可能会热衷于阅读此 , 这个和这个 。

如果您发现自己在设计上使用FSM的情况,则可能已经开始为实现相同接口的每个状态编写类。 一个好的设计可能是:

interface State { }
class State_1 implements State {}
class State_2 implements State {}
...

您可能有一个类可以管理这些状态以及它们之间的过渡,而另一个可以实现FSM的上下文(输入带状区域),另一个用于起始状态的接口,另一个用于结束状态的接口,依此类推。 许多类分散在许多文件中,使您无法快速跟踪它们。

还有另一种方法:使用枚举。

枚举本质上是类的列表,并且枚举的每个成员可能具有不同的实现。 假设我们要实现以下状态机:

初始化-('a')-> A
初始化-(else)->失败
A-('b')-> B A-('c')-> C A-('a')-> A A-(”)->结束 A-(其他)->失败 B-('c')-> C B-('b')-> B B-(”)->结束 B-(其他)->失败 C-('c')-> C C-(”)->结束 C-(其他)->失败

该FSM将验证以下正则表达式:^(a +)(b *)(c *)$。 我们可以将状态写成枚举状态的元素,如下所示:

interface State {public State next();
}
class Input {private String input;private int current;public Input(String input) {this.input = input;}char read() { return input.charAt(current++); }
}enum States implements State {Init {@Overridepublic State next(Input word) {switch(word.read()) {case 'a': return A;default: return Fail;}}},A {@Overridepublic State next(Input word) {switch(word.read()) {case 'a': return A;case 'b': return B;case 'c': return C;case '': return null;default: return Fail;}}},B {@Overridepublic State next(Input word) {switch(word.read()) {case 'b': return B;case 'c': return C;case '': return null;default: return Fail;}}},C {@Overridepublic State next(Input word) {switch(word.read()) {case 'c': return C;case '': return null;default: return Fail;}}},Fail {@Overridepublic State next(Input word) {return Fail;}};public abstract State next(Input word);
}

我们要做的是定义每个枚举中每个状态的转换。 每个过渡都会返回一个新状态,因此我们可以更有效地循环遍历它们:

State s;
Input in = new Input("aabbbc");
for(s = States.Init; s != null || s != States.Fail; s = s.next(in)) {}if(s == null) {System.out.printlin("Valid!");}
else {System.out.println("Failed");}

此时,我们要么验证了字符串,要么失败了。 这是一个简单而优雅的设计。

我们可以通过将最终状态与主要状态分开来进一步改善实现,以简化遍历的退出条件。 我们将定义另一个名为FinalState的接口,以及一个将包含所需退出状态的第二枚举(相应地更改States枚举):

interface FinalState extends State {}
enum FinalStates implements FinalState {Fail {@Overridepublic State next(Input word) {return Fail;}},Ok {@Overridepublic State next(Input word) {return End;}}
}

这样,遍历将有所简化:

for(s = States.Init; !(s instanceof FinalState); s = s.next(in)) {}
switch(s) {case Fail: System.out.printlin("Failed"); break;case Ok: System.out.println("Valid!"); break;default: System.out.println("Undefined"); break;
}

优点是(除了更简单的遍历之外),我们可以指定两个以上的最终状态。 在大多数情况下,FSM会有多个出口点,因此建议从长远来看最后一种改进。 您还可以将所有这些枚举和接口放在同一源文件中,并将整个逻辑放在一个位置,而不是浏览多个选项卡,以便了解流程的工作原理。

总之,使用枚举可以更紧凑,更有意义地实现FSM。 您将所有逻辑都放在一个文件中,并且所有遍历都是轻松的。 您还将获得更轻松的调试体验,因为已转换的状态的名称将显示在调试器中(变量s将相应地更改其值,并带有新状态的名称),而不必弄清楚您刚刚上过什么课。 总而言之,我认为这是一个好技术。

参考:我们的JCG合作伙伴 Attila-Mihaly Balazs 在Java中实现自动机   在Transylvania JUG博客上。


翻译自: https://www.javacodegeeks.com/2012/03/automaton-implementation-in-java.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/373392.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files这个文件找不到

在C:\Windows\Microsoft.NET\Framework64\v4.0.30319文件夹下面建立Temporary ASP.NET Files 文件夹(Framework64 注意64,这个可能是我们用的64位系统,但是vs2010不分32位还是64位,所以在C:\Windows\Microsoft.NET\Framework\v4.0…

java电脑运行视频演示_javaweb视频第一天(二)

无论通过哪种方式得到的class类对象,是同一个。比较的是地址码这里教会你:如何去使用class对象现在就知道这个:如何使用反射,并且说反射是实现了什么样的功能。如何通过反射得到里面的相应字段,得到里面的相应函数等等…

模型驱动 ModelDriven

ModelDriven:模型驱动,对所有action的模型对象进行批处理. 我们在开发中, 在action中一般是用实体对象,然后给实体对象get,set方法。 RegAction{   User user ;   //get/set} 然后在jsp页面中给action中的user属性绑定值是通过如下方式 &…

本月风味– Neo4j和Heroku

Neo4j今年早些时候发起了一项挑战,即“ 种子播云 ”,以使人们使用Neo4j附加组件在Heroku上创建模板或演示应用程序。 经过许多内部辩论之后,我决定进入,但由于缺乏想法而陷入绝望。 当我什么都没做的时候,这个主意就出…

1 + 11 + 1111+ 11111+ ..... + 11111(2016个) 结果是几位数

# -*- coding: utf-8 -*- """ Created on Mon Mar 21 20:38:06 2016author: yanjie """1 11 1111 11111 ..... 11111(2016个) 结果是几位数 用什么数据结构 有几个6 写算法a []; m 0; six 0; for i in range(2016,0,-1):b (im) % 10;m (…

[回归分析][10]--相关误差的问题

[回归分析][10]--相关误差的问题这一篇文章还是来分析相关误差的问题。 1.游程数 定义:游程数--残差穿过x-轴的次数 用这个可以检查如残差有一块在x轴上面,一块在x轴下面的情形。 如上面这样的残差 下面构造两个统计量: 其中 n…

Spring 3 MVC异常处理程序

我遇到的大多数Spring 3错误处理示例代码似乎都提供了其用法的最简单概述,但是,有人说,如何处理错误比正常代码的工作方式更为重要。 前一天,当我在Spring(2)错误处理程序中遇到一个简单的GOTCHA时&#xf…

java编译找不到符号_javac编译时找不到符号?

我是个新手,在linux使用java编程时,出现这个情况。我把要引的包放在classpath中,红色部分:export CLASSPATH.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$HADOOP_HOME/hadoop-1.0.4.core.jar:${CLASSPATH}通过echo $CLASSP…

全备份、差异备份和增量备份概念详述

全备份、差异备份和增量备份概念详述 1、完全备份(Full Backup) 备份全部选中的文件夹,并不依赖文件的存档属性来确定备份那些文件。在备份过程中,任何现有的标记都被清除,每个文件都被标记为已备份。换言之&#xff0…

微信接入登录功能access_token流程记录

提示:只有认证过的订阅号或者服务号才能获取access_token。 1.app微信登录第一步是,app调起来微信客户端,通过app端的配置,引入一个微信类库, 2.授权成功后,微信会返回你一个code。 将APP_ID替换成你在微信…

使用MVC模式制作游戏-教程和简介

游戏开发中一种有用的体系结构模式是MVC(模型视图控制器)模式。 它有助于分离输入逻辑,游戏逻辑和UI(渲染)。 在任何游戏开发项目的早期阶段,其实用性很快就会被注意到,因为它允许快速更改内容&…

boost

参考博客 http://www.cnblogs.com/lidabo/p/3805487.html http://www.cppblog.com/Robertxiao/archive/2013/01/06/197022.html http://www.cnblogs.com/finallyliuyu/archive/2013/05/23/3094246.html http://www.cnblogs.com/lidabo/p/3782193.html http://www.cnblogs.com/z…

moment格式换时间_不一样的日期、时间转换(moment.js)

无意中遇到了一种很奇怪的日期格式,从接口中返回的日期是这样的,如 2018-02-06T11:59:2208:00 。然而这却不是我们想要的,我们要的是这种,YYYY-MM-DD HH:mm:ss。那么这种是怎么转换的呢?这时候就可以使用一款很好用的日…

并发模式:生产者和消费者

在我15年的职业生涯中,生产者和消费者的问题是我仅遇到过几次。 在大多数编程情况下,我们正在做的事情是以同步方式执行功能,其中JVM或Web容器自行处理多线程的复杂性。 但是,在编写某些需要的用例时。 上周,我遇到了一…

POJ 1006 - Biorhythms (中国剩余定理)

B - BiorhythmsTime Limit:1000MS Memory Limit:10000KB 64bit IO Format:%I64d & %I64u Submit Status Practice POJ 1006Description 人生来就有三个生理周期,分别为体力、感情和智力周期,它们的周期长度为23天、28天和33天。每一个周期中…

子线程中更新UI线程的三个方法

1、通过handler方式,sendmessage。 多个类间传递比较麻烦,也懒的写... 2、线程中通过runOnUiThread() new Thread() { public void run() { //这儿是耗时操作,完成之后更新UI; runOnUiThread(new Runnab…

mysql limit acs_mysql查询操作

简单查询&#xff1a;select * from 表名;避免重复&#xff1a;select distinct 字段 from 表名;条件查询&#xff1a;select 字段,字段 from 表名 where id<5(条件);四则运算查询&#xff1a;select id,dep_id,id*dep_id from company.employee5 where id<5;定义显示格式…

作业管理系统数据字典

转载于:https://www.cnblogs.com/heyangcan/p/5312394.html

使用Hive和iReport进行大数据分析

每个JJ Abrams的电视连续剧疑犯追踪从主要人物芬奇先生一个下列叙述情节开始&#xff1a;“ 你是被监视。 政府拥有一个秘密系统-每天每天每小时都会对您进行监视的机器。 我知道是因为...我建造了它。 “当然&#xff0c;我们的技术人员知道得更多。 庞大的电气和软件工程师团…

docker集群管理

docker集群管理 ps&#xff1a;docker machine docker swarm docker compose 在Docker Machine发布之前&#xff0c;你可能会遇到以下问题&#xff1a; 你需要登录主机&#xff0c;按照主机及操作系统特有的安装以及配置步骤安装Docker&#xff0c;使其能运行Docker…