有限状态机和状态模式
有限状态机(Finite-State Machine)是一种计算模型,状态模式是一种设计模式,两者不可同日而语。但是,有限状态机可以通过状态模式来实现。
所谓的有限,指的是状态个数是有限的,每个状态可以迁移到零个到多个状态,输入的时间决定了状态往哪个方向迁移。
有限状态机的特征是离散、有限。但是,世界上绝大多数事物,没有办法使用状态机来表示,这些事物的状态比较复杂,可能有无限多个。比如,经济增长的变化,温度的变化。
当前状态/条件 | 状态A | 状态B |
---|---|---|
条件X | … | … |
条件Y | 状态B | … |
状态机可以归纳为:现态、事件、动作、次态。
- 现态:指的是对象当前所处的状态
- 事件:发生一个事件,可能执行状态迁移
- 动作:发生一个事件后执行的操作。事件发生会触发相应的动作。此时可能发生状态的迁移,也可能不发生。
- 次态:“次态”是相对于“现态”而言的,“次态”一旦被激活,就转变成新的“现态”了。
状态模式
状态模式,可以作为实现状态机的一种方式:
在软件开发过程中,对象需要根据不同的情况做出不同的行为,影响对象行为的一个或者多个属性我们把它称为状态。当有外部事件影响对象的状态发生改变时,对象的行为也会发生改变。状态模式可以在一定程度上优化密集的 if-else或者switch-case代码,类似条件判断语句会过于臃肿,可读性差,且不具备扩展性,维护难度也大。
状态模式的核心要点是把复杂的逻辑判断提取出来,用不同的类来表示,系统处于哪种情况,就使用相应的状态类来进行处理,这样做就能简化逻辑的判断。
但是状态模式也有缺点,最大的缺点就是会增加系统中类的数量,以后新增状态也要新增类,也有一定的复杂度。
从上图可以看出,状态模式主要有:
- Context 类:环境上下文,维护一个当前状态
- State 类:抽象类,定义对象的状态和行为
- ConcreteState 类:实现抽象对象所定义的行为
实现FSM
实现一个FSM包含了几个要素:状态的管理、状态的监控、状态的触发、状态触发后引发的动作。
状态模式实现
//抽象状态类
abstract class State {
public abstract void Handle(Context context);
}
//具体状态A类
class ConcreteStateA extends State {
public void Handle(Context context) {
System.out.println("当前状态是 A.");
context.setState(new ConcreteStateB());
}
}
//具体状态B类
class ConcreteStateB extends State {
public void Handle(Context context) {
System.out.println("当前状态是 B.");
context.setState(new ConcreteStateA());
}
}
//环境类
class Context {
private State state;
//定义环境类的初始状态
public Context() {
this.state = new ConcreteStateA();
}
//设置新状态
public void setState(State state) {
this.state = state;
}
//读取状态
public State getState() {
return (state);
}
//对请求做处理
public void Handle() {
state.Handle(this);
}
}
枚举实现
public interface IPositionFSM {
default IPositionFSM processFoo() {
return this;
}
default IPositionFSM processBar() {
return this;
}
}
public enum PositionFSM implements IPositionFSM {
State1 {
@Override
public IPositionFSM processFoo() {
return State2;
}
},
State2 {
@Override
public IPositionFSM processBar() {
return State1;
}
};
}
总结
状态模式实现FSM略显复杂,一般情况下推荐使用枚举的方式。
参考资料: