宇宙最强设计模式

状态机模式

状态机的要素

  1. 现态:现在的状态
  2. 条件:当条件被满足时,将触发一个动作,或者执行一次状态的转移
  3. 动作:条件被满足时,执行的动作,动作不是必须的
  4. 次态:将要到达的状态

注意:

  1. 动作是不稳定的,动作执行完毕就结束了
  2. 状态是稳定的,如果没有外部条件的触发,一个状态会一直持续下去。

状态机模式 - 图1 如上图,开始状态当满足c1条件时,将跳转到s1状态,并进行a1动作,请注意动作不是必须的。

以上是对状态图的介绍,那我我们如何实现一个状态机呢?最简单的方法是

  1. if(条件满足){
  2. 动作;
  3. 改变状态;
  4. }

但是如果状态机很复杂,那么我们就要有很多的判断,这不符合开闭原则,那么如何写一个高质量的状态转移代码呢?

实现1——古朴方式

  1. 使用枚举实现简单的状态机

使用枚举实现状态机来优雅你的状态变更逻辑 - 码农小胖哥 - 博客园 (cnblogs.com)

  1. 使用枚举实现复杂的状态机

Java秘术:用枚举构建一个状态机-阿里云开发者社区 (aliyun.com)

在这个小例子中,解析器的状态机处理一个ByteBuffer里的原始的XML。每一个状态都有自己的处理方法,如果没有足够的可用的数据,状态机可以回来再次获取更多的数据。状态之间的每一次变换都被定义,所有状态的代码在一个enum中。

  1. interface Context {
  2. ByteBuffer buffer();
  3. State state();
  4. void state(State state);
  5. }
  6. interface State {
  7. /**
  8. * @return true to keep processing, false to read more data.
  9. */
  10. boolean process(Context context);
  11. }
  12. enum States implements State {
  13. XML {
  14. public boolean process(Context context) {
  15. if (context.buffer().remaining() < 16) return false;
  16. // read header
  17. if(headerComplete)
  18. context.state(States.ROOT);
  19. return true;
  20. }
  21. }, ROOT {
  22. public boolean process(Context context) {
  23. if (context.buffer().remaining() < 8) return false;
  24. // read root tag
  25. if(rootComplete)
  26. context.state(States.IN_ROOT);
  27. return true;
  28. }
  29. }
  30. }
  31. public void process(Context context) {
  32. socket.read(context.buffer());
  33. while(context.state().process(context));
  34. }

实现2——使用状态机引擎

Spring-Statemachine 状态机 - 简书 (jianshu.com)

工单引擎Flowable

安装flowable ui界面

  1. docker run -p8080:8080 flowable/flowable-ui

http://localhost:8080/flowable-ui admin/test

文档

Flowable Open Source Documentation · Reference and User Guides

代理模式

代理模式(代理设计模式)详解 (biancheng.net)