狀態機適用場景:
C的操作,需要等到A、B的兩個操作(A、B順序操作),那就需要在 A、B之間創建一個狀態機(state machine),C的操作需要狀態機達到某一個狀態才能進行
1. Overview
java版的狀態機的原理其實就是java中的枚舉類Enum,所以在進行狀態機設計之前,先學習一下(回顧一個java Enum)
2. Java Enums
一個簡單的例子:員工請假系統,員工到HR那離(submitted)-> 部門領導(Escalated) -> 部門經理(Approved)
public enum LeaveRequestState { Submitted, Escalated, Approved }
我們可以這樣引用:
LeaveRequestState state = LeaveRequestState.Submitted;
java的枚舉也可以包含方法,我們可以在枚舉類中寫一個抽象方法(abstract),這樣枚舉類中的每個成員都會繼承該方法,這個就是java版狀態機的核心所在
public enum LeaveRequestState { Submitted { @Override public String responsiblePerson() { return "Employee"; } }, Escalated { @Override public String responsiblePerson() { return "Team Leader"; } }, Approved { @Override public String responsiblePerson() { return "Department Manager"; } }; public abstract String responsiblePerson(); }
注意上面的逗號,以及抽象方法前的分號
在下面的例子中, 我們使用上面代碼中的 responsiblePerson() 方法. 這就是一個典型的狀態機. 我們想知道"Escalated "的“狀態”(實際是審批人), 那就會返回結果 “Team Leader”:
LeaveRequestState state = LeaveRequestState.Escalated;
assertEquals("Team Leader", state.responsiblePerson());
同樣的 “Department Manager”:
LeaveRequestState state = LeaveRequestState.Approved;
assertEquals("Department Manager", state.responsiblePerson());
3. State Machines
狀態機又稱有限狀態機,是一個建立在抽象機器上的計算模型,這個狀態機在給定的時間內,只能有一個狀態,而每一個狀態又可以轉換為其他狀態(其他狀態也是我們自己定義的)
4. Enums as State Machines
public enum LeaveRequestState { Submitted { @Override public LeaveRequestState nextState() { return Escalated; } @Override public String responsiblePerson() { return "Employee"; } }, Escalated { @Override public LeaveRequestState nextState() { return Approved; } @Override public String responsiblePerson() { return "Team Leader"; } }, Approved { @Override public LeaveRequestState nextState() { return this; } @Override public String responsiblePerson() { return "Department Manager"; } }; public abstract LeaveRequestState nextState(); public abstract String responsiblePerson(); }
LeaveRequestState state = LeaveRequestState.Submitted; state = state.nextState(); assertEquals(LeaveRequestState.Escalated, state); state = state.nextState(); assertEquals(LeaveRequestState.Approved, state); state = state.nextState(); assertEquals(LeaveRequestState.Approved, state);