宇宙最强设计模式
状态机模式
状态机的要素
- 现态:现在的状态
- 条件:当条件被满足时,将触发一个动作,或者执行一次状态的转移
- 动作:条件被满足时,执行的动作,动作不是必须的
- 次态:将要到达的状态
注意:
- 动作是不稳定的,动作执行完毕就结束了
- 状态是稳定的,如果没有外部条件的触发,一个状态会一直持续下去。
如上图,开始状态当满足c1条件时,将跳转到s1状态,并进行a1动作,请注意动作不是必须的。
以上是对状态图的介绍,那我我们如何实现一个状态机呢?最简单的方法是
if(条件满足){动作;改变状态;}
但是如果状态机很复杂,那么我们就要有很多的判断,这不符合开闭原则,那么如何写一个高质量的状态转移代码呢?
实现1——古朴方式
- 使用枚举实现简单的状态机
使用枚举实现状态机来优雅你的状态变更逻辑 - 码农小胖哥 - 博客园 (cnblogs.com)
- 使用枚举实现复杂的状态机
Java秘术:用枚举构建一个状态机-阿里云开发者社区 (aliyun.com)
在这个小例子中,解析器的状态机处理一个ByteBuffer里的原始的XML。每一个状态都有自己的处理方法,如果没有足够的可用的数据,状态机可以回来再次获取更多的数据。状态之间的每一次变换都被定义,所有状态的代码在一个enum中。
interface Context {ByteBuffer buffer();State state();void state(State state);}interface State {/*** @return true to keep processing, false to read more data.*/boolean process(Context context);}enum States implements State {XML {public boolean process(Context context) {if (context.buffer().remaining() < 16) return false;// read headerif(headerComplete)context.state(States.ROOT);return true;}}, ROOT {public boolean process(Context context) {if (context.buffer().remaining() < 8) return false;// read root tagif(rootComplete)context.state(States.IN_ROOT);return true;}}}public void process(Context context) {socket.read(context.buffer());while(context.state().process(context));}
实现2——使用状态机引擎
Spring-Statemachine 状态机 - 简书 (jianshu.com)
工单引擎Flowable
安装flowable ui界面
docker run -p8080:8080 flowable/flowable-ui
http://localhost:8080/flowable-ui admin/test
文档
Flowable Open Source Documentation · Reference and User Guides
