有限状态机与state模式

james_razor 2003-02-28 10:07:10
一个项目的开发过程中,需要实现一个有限状态机,于是马上想到用state模式实现,效果还算不错,但有几个问题想和各位探讨一下。
首先,使用state模式是为了消除复杂的if-else语句或者switch-case语句,但是由于各个模式间转换也会有非常多条件,状态类中if-else语句或者switch-case语句仍然避免不了。
其次,本来设计的所有的状态类都是singlton模式,不在state中存储局部状态。一、是为了方便编程,不用动态创建,也就不用考虑销毁的问题,因此消除了内存泄漏的隐患;二,有限状态机是和每个客户绑定的,不同的客户对应不同的有限状态机,我们不想让系统在状态子类上的开销太大。但这样,也带来的一个问题,由于有限状态机的状态太多,而且到现在仍未确定,也就是说,有增加新的状态子类的可能,而且会很多。为了解决这个问题,我在后期加的状态类中不再使用singlton模式,而是用普通的对象创建方式,以便在里面存储状态,也就是说用一个状态类来替代可能增加的一系列的状态转换。但这使得系统设计不纯,可能会给以后的维护带来文题。
还有,刚才看到一篇文章, http://comcamp.myrice.com/techarticles/pattern/state.htm 上面认为state模式和有限状态机本质上是不同的,不知有何深意。

小砖半块,望各位大虾于以指正。
...全文
3155 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
jeffyan77 2003-03-06
  • 打赏
  • 举报
回复
呵呵,不买没有关系,单例模式那一章是免费发送的
http://www.webendshere.com/javapatterns/preview/preview.html
james_razor 2003-03-06
  • 打赏
  • 举报
回复
多谢jeffyan77,关于double-check idiom的那部分确实很好。
欢迎大家继续讨论,如果没有,我就要结帖了。
keios 2003-03-05
  • 打赏
  • 举报
回复
to 楼主
我做过的telnet客户端也是使用了state模式,感觉和你很相似,也是先看了
TCP/IP vol 3 上的实现,后改为state的。:)
不过我没有使用singleton,原因是我需要在一个进程中存在多个状态机,
感觉使用的还是比较成功的,各状态比较清晰,子状态也可明确表示。
维护的问题,我想只要文档写的足够清晰,稍微看一下代码就会非常明白的。
不过对设计模式了解的还是不够,jeff说的Immutable第一次听说,努力学习ing
james_razor 2003-03-05
  • 打赏
  • 举报
回复
非常感谢jeffyan77,不过您的书我没看过暂时也不想买,太厚了,呵呵:)
Norwaywoods 2003-03-05
  • 打赏
  • 举报
回复
gz
jeffyan77 2003-03-05
  • 打赏
  • 举报
回复
关于单例模式继承的困难,我在很多场合下讲过,最详细的就是我的书。

状态机,推广而来的状态图,必须使用多个设计模式组成的模式语言(pattern language)描述,只有状态模式是不够的,先熟悉前人的结果吧:
http://jerry.cs.uiuc.edu/~plop/plop98/final_submissions/P22.pdf
以及文中引用的文献。


james_razor 2003-03-05
  • 打赏
  • 举报
回复
2 keios:
状态机类我没用singleton,也是由于多个实例的问题(telnet服务器要为多个客户端服务)。但大部分的状态子类我用的是singleton模式。
总的来说,感觉state模式在这个比较简单的项目上就足够了,复杂的状态机还需要更多的模式,jeffyan77推荐的那篇文章应该是非常好的参考资料。
richardluopeng 2003-03-04
  • 打赏
  • 举报
回复
hehe
james_razor 2003-03-04
  • 打赏
  • 举报
回复
多谢二位。
2 MagicJohn:
我做的是telnet服务器,Internetworking with TCP/IP Vol.III一书上关于Telnet服务器协商协议就是用有限状态机完成的。只不过他用的是表驱动的方法,我在实现的时候,把它换成了state模式,其实我觉得用state模式来实现FSM还是非常适合的。尤其在状态不是很多(6~10),各个状态间切换条件也不是很多的情况下(2~3),Design Pattern一书中state模式就是用在TCP网络协议上。
在state模式中使用singleton模式也是Design Pattern上介绍的一种实现方法,在多次创建和一次创建之间,我首先选择了一次创建,singleton全局访问的特性使得编程比较简单,也不必考虑内存泄漏的问题。但就如我上面所说,实际使用当中由于状态较多,而且多数状态只有一条跳转路径,为每一个这样的状态创建一个类觉得很不经济,于是又回到了最普通的类创建方法,在类中记录状态,代表多个状态转换。
2 jeffyan77:
singleton的模式,构造函数是protected,不是为了继承用的吗?不过如果增加一个新的子类,父类的getInstance方法就要重写而去调用子类的getInstance方法。这是我的实现方法。
我现在实现的state模式,状态的转换在内部决定,这样是不是就能和状态机对应上了?
jeffyan77 2003-03-04
  • 打赏
  • 举报
回复
第一、我看了一下楼主所给出的链接,上面有这么一段话:

“(3) 绝大多数情况下,State不会有描述自身状态的内部数据,所以应该运用Singleton模式。”

这是没有道理的,单例模式不是干这个用的。如果一个对象没有自己的状态的话,应当考虑使用Immutable模式。但凡复杂一点的状态必然有自己的继承等级结构,单例模式不适合于继承,所以实际可行性也很小。作者恐怕没有真的实践过自己的主张,对读者很有误导作用。

第二、上面文中所提到的下面这段话
“(6) State与状态机之间有着本质的区别。状态机着重于定义状态转换,而State着重于描述与状态相关的行为。 ”
是有道理的。常常有人误将状态模式与状态机混淆起来,实际上状态机的内容比状态模式要广泛得多。状态模式是对象的行为模式,它描述状态所带有的行为,状态模式本身不描述状态如何转换。一般而言,状态模式仅仅接受状态的转换,决定是否进行状态转换可以来自于外部,也可以来自于状态对象内部,这就是说状态模式不在乎状态转换决定在什么地方。

第三、上面文中所提到的状态模式的“优点:避免了为判断状态而产生的巨大的if或case语句”是对的,但不精辟。

并不是所有的条件转移语句都应当重构,即便确定需要重构,也是将之用polymorphism取代,而不是使用状态模式取代。如果说状态模式可以用来取代“巨大的if或case语句”,那么几乎所有的设计模式都可以做这个用途,因为几乎所有的设计模式都利用了polymorphism。

最后,关于对象过多的问题,从系统设计的角度上讲,不怕状态对象过多,而怕不宜于扩展/维护。多不一定意味着难于扩展/维护,少不见得就意味着好扩展/维护。当然,如果真的非常多,难于扩展/维护的话,可以考虑进行优化。具体怎么优化,就是一个必须研究了软件需求之后才能回答的问题。
MagicJohn 2003-03-03
  • 打赏
  • 举报
回复
model的复合实用确实是比较复杂的问题,但是不知道你开发的是关于哪一方面的系统。基于什么因素考虑使用singlton模式和state模式,这样就会便于大家讨论。
james_razor 2003-03-03
  • 打赏
  • 举报
回复
各位没什么想法吗?

51,395

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧