介绍
有限状态机通常用于模拟序列逻辑,换句话说,就是用于代表和控制执行流程。
有限状态机所需条件:
- 一个物体只有固定的几种状态(例如交通灯只有绿灯、黄灯和红灯三个状态)。
- 有固定的变化顺序(例如交通灯只能绿灯->黄灯->红灯->绿灯循环)
- 物体同一时间点上只有一种状态。
例子
这里拿一个空调做例子,图是用了别人的,这里说明下下面三个状态的意思:
Off:空调关机
FanOnly:空调仅吹风
Cool:空调制冷
原始的解决办法
StateEnum
用枚举类定义三种状态
package org.example.origin;
public enum StateEnum {
POWER_OFF, FAN_ONLY, COOL
}
OriginAction
pressPowerOff()
表示点开关按钮,pressCool()
表示点击制冷按钮。
package org.example.origin;
public class OriginAction {
private StateEnum stateEnum;
public OriginAction() {
this.stateEnum = StateEnum.POWER_OFF;
}
public void pressPowerOff() {
// 关机->吹风
if (stateEnum == StateEnum.POWER_OFF) {
this.stateEnum = StateEnum.FAN_ONLY;
System.out.println("Power on succeed.");
} else {
// 吹风或制冷->关机
this.stateEnum = StateEnum.POWER_OFF;
System.out.println("Power off succeed.");
}
}
public void pressCool() {
if (stateEnum == StateEnum.POWER_OFF) {
System.out.println("Cool failed because power off.");
} else if (stateEnum == StateEnum.FAN_ONLY) {
// 吹风->制冷
this.stateEnum = StateEnum.COOL;
System.out.println("Open cool succeed.");
} else {
// 制冷->吹风
this.stateEnum = StateEnum.FAN_ONLY;
System.out.println("Close cool succeed");
}
}
}
OriginTest
编写测试类
package org.example.origin;
public class OriginTest {
public static void main(String[] args) {
OriginAction originAction = new OriginAction();
originAction.pressCool();
originAction.pressPowerOff();
originAction.pressCool();
originAction.pressCool();
originAction.pressPowerOff();
}
}
执行结果:
Cool failed because power off.
Power on succeed.
Open cool succeed.
Close cool succeed
Power off succeed.
使用有限状态机解决
FiniteStateMachineEnum
这里使用了 Java 的枚举类,确保了类型约束。
package org.example.state;
public enum FiniteStateMachineEnum {
POWER_OFF {
// 关机->吹风
@Override
public FiniteStateMachineEnum pressPowerOff() {
System.out.println("Power on succeed.");
return FiniteStateMachineEnum.FAN_ONLY;
}
// 无效
@Override
public FiniteStateMachineEnum pressCool() {
System.out.println("Cool failed because power off.");
return FiniteStateMachineEnum.POWER_OFF;
}
},
FAN_ONLY {
// 吹风->关机
@Override
public FiniteStateMachineEnum pressPowerOff() {
System.out.println("Power off succeed.");
return FiniteStateMachineEnum.POWER_OFF;
}
// 吹风->制冷
@Override
public FiniteStateMachineEnum pressCool() {
System.out.println("Open cool succeed.");
return FiniteStateMachineEnum.COOL;
}
},
COOL {
// 制冷->关机
@Override
public FiniteStateMachineEnum pressPowerOff() {
System.out.println("Power off succeed.");
return FiniteStateMachineEnum.POWER_OFF;
}
// 制冷->吹风
@Override
public FiniteStateMachineEnum pressCool() {
System.out.println("Close cool succeed");
return FiniteStateMachineEnum.FAN_ONLY;
}
};
public abstract FiniteStateMachineEnum pressPowerOff();
public abstract FiniteStateMachineEnum pressCool();
}
FiniteStateMachineTest
编写测试类
package org.example.state;
public class FiniteStateMachineTest {
public static void main(String[] args) {
FiniteStateMachineEnum stateEnum = FiniteStateMachineEnum.POWER_OFF;
stateEnum.pressCool()
.pressPowerOff()
.pressCool()
.pressCool()
.pressPowerOff();
}
}
执行结果:
Cool failed because power off.
Power on succeed.
Open cool succeed.
Close cool succeed
Power off succeed.
总结
两种方法的运行结果是一样的,但是有限状态机的写法更加简洁明了。传统方法在简单的条件下还可以应付,但是如果面对复杂的执行逻辑顺序,只有通过有限状态机来解决了,而且代码更加简洁明了,易于维护。
原创文章,作者:Smith,如若转载,请注明出处:https://www.inlighting.org/archives/finite-state-machine-in-java