原文地址:https://www.inlighting.org/archives/finite-state-machine-in-java
介紹
有限狀態(tài)機(jī)通常用于模擬序列邏輯,換句話說,就是用于代表和控制執(zhí)行流程。
有限狀態(tài)機(jī)所需條件:
- 一個(gè)物體只有固定的幾種狀態(tài)(例如交通燈只有綠燈、黃燈和紅燈三個(gè)狀態(tài))四苇。
- 有固定的變化順序(例如交通燈只能綠燈->黃燈->紅燈->綠燈循環(huán))
- 物體同一時(shí)間點(diǎn)上只有一種狀態(tài)。
例子
這里拿一個(gè)空調(diào)做例子,圖是用了別人的臀栈,這里說明下下面三個(gè)狀態(tài)的意思:
Off:空調(diào)關(guān)機(jī)
FanOnly:空調(diào)僅吹風(fēng)
Cool:空調(diào)制冷
原始的解決辦法
StateEnum
用枚舉類定義三種狀態(tài)
package org.example.origin;
public enum StateEnum {
POWER_OFF, FAN_ONLY, COOL
}
OriginAction
pressPowerOff()
表示點(diǎn)開關(guān)按鈕,pressCool()
表示點(diǎn)擊制冷按鈕挠乳。
package org.example.origin;
public class OriginAction {
private StateEnum stateEnum;
public OriginAction() {
this.stateEnum = StateEnum.POWER_OFF;
}
public void pressPowerOff() {
// 關(guān)機(jī)->吹風(fēng)
if (stateEnum == StateEnum.POWER_OFF) {
this.stateEnum = StateEnum.FAN_ONLY;
System.out.println("Power on succeed.");
} else {
// 吹風(fēng)或制冷->關(guān)機(jī)
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) {
// 吹風(fēng)->制冷
this.stateEnum = StateEnum.COOL;
System.out.println("Open cool succeed.");
} else {
// 制冷->吹風(fēng)
this.stateEnum = StateEnum.FAN_ONLY;
System.out.println("Close cool succeed");
}
}
}
OriginTest
編寫測(cè)試類
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();
}
}
執(zhí)行結(jié)果:
Cool failed because power off.
Power on succeed.
Open cool succeed.
Close cool succeed
Power off succeed.
使用有限狀態(tài)機(jī)解決
FiniteStateMachineEnum
這里使用了 Java 的枚舉類权薯,確保了類型約束姑躲。
package org.example.state;
public enum FiniteStateMachineEnum {
POWER_OFF {
// 關(guān)機(jī)->吹風(fēng)
@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 {
// 吹風(fēng)->關(guān)機(jī)
@Override
public FiniteStateMachineEnum pressPowerOff() {
System.out.println("Power off succeed.");
return FiniteStateMachineEnum.POWER_OFF;
}
// 吹風(fēng)->制冷
@Override
public FiniteStateMachineEnum pressCool() {
System.out.println("Open cool succeed.");
return FiniteStateMachineEnum.COOL;
}
},
COOL {
// 制冷->關(guān)機(jī)
@Override
public FiniteStateMachineEnum pressPowerOff() {
System.out.println("Power off succeed.");
return FiniteStateMachineEnum.POWER_OFF;
}
// 制冷->吹風(fēng)
@Override
public FiniteStateMachineEnum pressCool() {
System.out.println("Close cool succeed");
return FiniteStateMachineEnum.FAN_ONLY;
}
};
public abstract FiniteStateMachineEnum pressPowerOff();
public abstract FiniteStateMachineEnum pressCool();
}
FiniteStateMachineTest
編寫測(cè)試類
package org.example.state;
public class FiniteStateMachineTest {
public static void main(String[] args) {
FiniteStateMachineEnum stateEnum = FiniteStateMachineEnum.POWER_OFF;
stateEnum.pressCool()
.pressPowerOff()
.pressCool()
.pressCool()
.pressPowerOff();
}
}
執(zhí)行結(jié)果:
Cool failed because power off.
Power on succeed.
Open cool succeed.
Close cool succeed
Power off succeed.
總結(jié)
兩種方法的運(yùn)行結(jié)果是一樣的,但是有限狀態(tài)機(jī)的寫法更加簡(jiǎn)潔明了崭闲。傳統(tǒng)方法在簡(jiǎn)單的條件下還可以應(yīng)付肋联,但是如果面對(duì)復(fù)雜的執(zhí)行邏輯順序,只有通過有限狀態(tài)機(jī)來解決了刁俭,而且代碼更加簡(jiǎn)潔明了橄仍,易于維護(hù)。