Java狀態(tài)機(jī)的一種優(yōu)雅寫法分享
狀態(tài)機(jī)是一種數(shù)學(xué)模型,對(duì)于我們業(yè)務(wù)實(shí)現(xiàn)有很大的幫助。
我們可以用非常多的方法實(shí)現(xiàn)狀態(tài)機(jī),比如用茫茫多的if-else來進(jìn)行條件判斷,但是這種原始的方法并不夠優(yōu)雅,這篇文章就來介紹一個(gè)狀態(tài)機(jī)優(yōu)雅的實(shí)現(xiàn)方法。
話不多說,直接進(jìn)入正題。
假設(shè)我們有兩個(gè)狀態(tài)

這個(gè)狀態(tài)轉(zhuǎn)換非常簡(jiǎn)單,我們來試著用java實(shí)現(xiàn)一下
程序結(jié)構(gòu)如下圖

我們先來介紹一下狀態(tài)的表示
public class StateTransaction {
// 當(dāng)前狀態(tài)
private StateEnum currentState;
// 相對(duì)應(yīng)動(dòng)作
private ActionEnum action;
// 下一個(gè)狀態(tài)
private StateEnum nextState;
// 相應(yīng)事件
private Event event;
public StateTransaction() {
}
public StateEnum getCurrentState() {
return currentState;
}
public ActionEnum getAction() {
return action;
}
public StateEnum getNextState() {
return nextState;
}
public Event getEvent() {
return event;
}
// 鏈?zhǔn)匠跏蓟瘜?duì)象
public StateTransaction source(StateEnum state) {
currentState = state;
return this;
}
public StateTransaction when(ActionEnum action) {
this.action = action;
return this;
}
public StateTransaction target(StateEnum state) {
nextState = state;
return this;
}
public StateTransaction how(Event event) {
this.event = event;
return this;
}
}可以看到,表示狀態(tài)的量一共有四個(gè),分別是:
- currentState:表示當(dāng)前狀態(tài)
- action:表示相應(yīng)動(dòng)作
- nextState:表示下一個(gè)狀態(tài)
- event:表示相應(yīng)事件
這個(gè)四元組的含義就是,當(dāng)處于currentState狀態(tài)的時(shí)候,如果發(fā)生了action動(dòng)作,就會(huì)轉(zhuǎn)移到nextState狀態(tài),并且會(huì)觸發(fā)event事件的響應(yīng)。
注意看鏈?zhǔn)匠跏蓟乃膫€(gè)方法,這四個(gè)方法的定義讓狀態(tài)的初始化變得很優(yōu)雅。
接著來看一下事件,Event是一個(gè)接口,其他具體的事件實(shí)現(xiàn)該接口進(jìn)行某些操作,我們這個(gè)程序就直接打印一些信息,不做復(fù)雜的操作
public interface Event {
public String handle();
}
public class PlayBasketballEvent implements Event{
@Override
public String handle() {
System.out.println("開始打籃球");
return "開始打籃球";
}
}
public class SingDanceRapEvent implements Event{
@Override
public String handle() {
System.out.println("開始唱,跳,rap");
return "開始唱,跳,rap";
}
}
除此之外,我們還要定義兩個(gè)枚舉類,分別表示狀態(tài)和動(dòng)作
public enum StateEnum {
// 打籃球
PLAY_BASKETBALL,
// 唱跳rap
SING_DANCE_RAP
}
public enum ActionEnum {
// 音樂起
MUSIC_ON,
// 音樂結(jié)束
MUSIC_OFF
}
上面準(zhǔn)備工作都做完后,我們需要一個(gè)狀態(tài)機(jī)類,來進(jìn)行狀態(tài)轉(zhuǎn)移
public class StateMachine {
// 存儲(chǔ)狀態(tài)信息
private List<StateTransaction> stateTransactionList;
// 記錄當(dāng)前狀態(tài)
private StateEnum currentState;
public StateMachine(StateEnum state) {
currentState = state;
stateTransactionList = new ArrayList<>();
}
// 添加一條狀態(tài)信息
public StateTransaction addone() {
StateTransaction stateTransaction = new StateTransaction();
stateTransactionList.add(stateTransaction);
return stateTransaction;
}
// 進(jìn)行狀態(tài)轉(zhuǎn)移
public StateTransaction execute(ActionEnum action) {
for(int i=0; i<stateTransactionList.size(); i++) {
if(currentState==stateTransactionList.get(i).getCurrentState() &&
action==stateTransactionList.get(i).getAction()) {
stateTransactionList.get(i).getEvent().handle();
currentState = stateTransactionList.get(i).getNextState();
return stateTransactionList.get(i);
}
}
return null;
}
}上述代碼有兩個(gè)方法比較關(guān)鍵,分別是addone()和execute()
先來說addone(),方法首先初始化一個(gè)StateTransaction對(duì)象,然后放到List里面,最后將這個(gè)對(duì)象返回,我們拿到這個(gè)對(duì)象就可以往里面填內(nèi)容了。
再說說execute(),這個(gè)方法接收ActionEnum作為參數(shù),然后會(huì)遍歷列表,尋找一條當(dāng)前狀態(tài)經(jīng)過相應(yīng)動(dòng)作變化得到的下一個(gè)對(duì)象的這么一個(gè)狀態(tài)信息,如果找到了就執(zhí)行event中的handle()方法,并且將當(dāng)前狀態(tài)進(jìn)行轉(zhuǎn)移,最后將StateTransaction返回,如果沒找到就返回null。
最后來看一下初始化的方法
public class StateMachineTest {
public static void main(String[] args) {
StateMachine machine = new StateMachine(StateEnum.PLAY_BASKETBALL);
// 打籃球的時(shí)候,一旦音樂起,就會(huì)開始唱跳rap
machine.addone().source(StateEnum.PLAY_BASKETBALL).when(ActionEnum.MUSIC_ON)
.target(StateEnum.SING_DANCE_RAP).how(new SingDanceRapEvent());
// 唱跳rap的時(shí)候,一旦音樂停止,就會(huì)開始打籃球
machine.addone().source(StateEnum.SING_DANCE_RAP).when(ActionEnum.MUSIC_OFF)
.target(StateEnum.PLAY_BASKETBALL).how(new PlayBasketballEvent());
machine.execute(ActionEnum.MUSIC_ON);
machine.execute(ActionEnum.MUSIC_OFF);
}
}可以看到,我們直接用鏈?zhǔn)降姆椒ň湍軇?chuàng)建一條狀態(tài)轉(zhuǎn)移信息,非常優(yōu)雅
程序輸出如下

以上就是Java狀態(tài)機(jī)的一種優(yōu)雅寫法分享的詳細(xì)內(nèi)容,更多關(guān)于Java狀態(tài)機(jī)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
HttpClient實(shí)現(xiàn)調(diào)用外部項(xiàng)目接口工具類的示例
下面小編就為大家?guī)硪黄狧ttpClient實(shí)現(xiàn)調(diào)用外部項(xiàng)目接口工具類的示例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-10-10
基于javamelody監(jiān)控springboot項(xiàng)目過程詳解
這篇文章主要介紹了基于javamelody監(jiān)控springboot項(xiàng)目過程詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11
java并發(fā)中DelayQueue延遲隊(duì)列原理剖析
DelayQueue隊(duì)列是一個(gè)延遲隊(duì)列,本文將結(jié)合實(shí)例代碼,詳細(xì)的介紹DelayQueue延遲隊(duì)列的源碼分析,感興趣的小伙伴們可以參考一下2021-06-06

