状态机学习与思考

1、 基本概念

1.1 状态

状态:是事物的一种属性,指事物表现出来的行为和形态。对象状态是指对象或所属类的的所有属性的当前值

1.2状态机

状态机图即为状态机,实质上是由一种由状态、转移、事件和动作组成的状态机。它描述了一个对象在生命周期内所经历的各种状态,状态之间的转移,发生转移的动因、条件以及转移中所执行的活动。

状态机可归纳为4个要素,即现态、条件、动作、次态。“现态”和“条件”是因,“动作”和“次态”是果。

①现态:是指当前所处的状态。

②条件:又称为“事件”,当一个条件被满足,将会触发一个动作,或者执行一次状态的迁移。

③动作:条件满足后执行的动作。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作不是必需的,当条件满足后,也可以不执行任何动作,直接迁移到新状态。

④次态:条件满足后要迁往的新状态。“次态”是相对于“现态”而言的,“次态”一旦被激活,就转变成新的“现态”了。

1.3 状态的转移

一个处于源状态的对象当满足一定条件时,会执行相应的动作,然后进入目标状态。可以从一个状态发出一个或多个状态转移,前提是转移要唯一。

自转移

源状态和目标状态相同,所包含的动作和事件 与 转移 完全相同。不改变对象状态,只导致对象状态的中断

内部转移

在不离开一个状态的情况下连续执行多个动作的情形称为内部转移

1.4 判断与决策点

表示工作流基于监护条件将出现分支的位置

1.5 事件

指示状态之间发生变化的条件,可以是内部事件(如异常)也可以是外部事件;可以是同步也可以是异步事件

  • 调用事件:同步,代表一个操作的调用
  • 信号事件:异步,信号是对象异步发送并由一个对象接收的具有名字的对象。比如:消息
  • 变化事件:是状态中的一个变化或者某些条件满足的事件,一般用when表示
  • 时间事件:经过一定时间或达到某个绝对时间后发生的事件(如task)【绝对】
  • 延迟事件:延迟响应直到某个合适的时刻才执行(如ScheduledThreadPoolExecutor)【相对】

无论异步还是同步,特别是对异步状态机而言,状态机内部不能在某个状态发生等待、阻塞等情况,而应该是标记状态后返回,把执行的机会让给其他任务或逻辑体。之后条件达到的情况下,通过事件分发机构调用状态机的运行。

2. 状态机的好处

古老的状态图的代码实现是通过 if-else或swich实现,但是这种方法代码太过复杂,逻辑不清晰,可读性较差,而程序本身没有保持自身持续运行的必要性。所以当一个状态的扭转有多个分支时,应该使用状态机。每个状态当得到事件的触发时会产生相应的行为,状态发生变化。所以状态机 降低了程序的复杂度、提高了可读性。

2. 状态机的使用

2.1 设计状态

状态是指在对象的生命周期中满足某些条件、执行某些活动或等待某些事件的条件。根据业务场景找出所有会出现的状态,一般情况下当一个状态的扭转出现多个分支时,则可以把这个状态设定为其中的一个状态机

2.2 状态迁移路线

有了状态表后,确认状态的迁移路线,不能跨状态迁移

2.3 重新整理状态表

绘制状态机图时,需要将状态设定在合理的位置,然后使用之前的状态迁移路线连接,这一步相当于是前两步的综合,不过很重要,最终的图示以这个为准,合理的状态布置除了便于理解之外,还利于代码的编写。

2.4 1️以状态的迁移作为事务的边界

在分布式系统中,如何保证事务问题,可以根据状态机的扭转来作为事务的边界,在一个状态迁移里的一系列行为应该保证事务一致(失败重试 | 失败回滚 | 其他)。可以对流程进行拆分,把一个状态迁移拆分为一个小流程,在这个小流程里事务一致,如果不根据状态的迁移拆分小流程,那在这个大流程里多个子业务流程的事务机制为一个,可能每个子流程的事务机制是不一样的(失败重试 | 失败回滚 | 其他)。并且实际上每一个条件满足或事件发生时只会有其中的一个小流程会执行

3. 延伸:状态模式

3.1 定义

状态模式:类的行为是基于它的状态改变的,我们需要创建 表示各种状态的对象 和 一个行为随着状态对象改变而改变的 context 对象。

3.1 作用

对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。当代码有大量与对象状态有关的条件语句时可以使用

  1. 封装了转换规则
  2. 允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块
  3. 将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为
//状态接口
public interface State {
   public void doAction(WaterDispenser context);
}

//满桶状态
public class FullState implements State {
   public void doAction(WaterDispenser context) {
      System.out.println("Water is pouring!");
      if(context.getCapacity() == 0){
           context.setStage(new NullState()); //内部转换状态
           //something else...比如:饮水机发出警告,通知装水
      }
   }
}


//空桶状态
public class NullState implements State {
   public void doAction(WaterDispenser context) {
      System.out.println("There is not water poured!");
}

//上下文 -- 含有状态的对象
public class WaterDispenser {
   private State state;
   private static int capacity = 20;
 
    public boolean press(){
        capacity--;
        dispenserState.doAction(); 
    }
    
   public void setState(State state){
      this.state = state;     
       //something else...
   }
 
   public State getState(){
      return state;
   }
    
    public int getCapacity(){
        return capacity;
    }
    
    public void setCapacityFull(){
        capacity = 20;
    }
}

//测试
public class Test {
    public static void main(String[] args) {
        WaterDispenser dispenser = new WaterDispenser(new FullState());
        for (int i = 0; i < 100; ++i) {
            dispenser.press();
        }
    }
}
    
 //非状态模式下:如果拥有很多状态,则会有很多if-else
    public class WaterDispenser {
    private static int capacity = 20;
    public void press() {
        capacity--;
        if (capacity <= 0) {
            System.out.println("There is not water poured!");
        } else {
            System.out.println("Water is pouring!");
        }
    }
}

状态机和状态模式的区别

状态机是一个对象处于某种形态,当受到一定条件或事件时(外部环境),发生一系列行为(自身行为或其他一系列动作,可能并非本类行为)

状态模式是当前类(比如饮水机)的行为根据不同状态自身产生不同的行为,不是受外部环境变化,以及不会对其他非关联类产生的一系列行为

你可能感兴趣的:(Java,/,Java虚拟机,/,javaweb,架构/分布式)