我正在爲我的應用程序實現Java中的狀態模式,並且需要很少的說明。實現狀態模式
狀態機有5個狀態狀態1到狀態5. 總共有5個事件(Event1到Event5)導致狀態轉換。 並非所有事件都適用於所有州。如果事件不適用於該特定狀態,應用程序將拋出異常。
當狀態機得到初始化時,它從狀態1開始。
以下是接口和上下文類。
/*
Interface defining the possible events in each state.
Each Implementer will handle event in a different manner.
*/
public interface State {
/*
Handlers for each event. Each Implementer will handle the vent in a different manner.
*/
public void handleEvent1(StateContext context);
public void handleEvent2(StateContext context);
public void handleEvent3(StateContext context);
public void handleEvent4(StateContext context);
public void handleEvent5(StateContext context);
// Method to enter state and do some action.
public void enter(StateContext context);
// Method to exit state and do some clean-up activity on exit .
public void exit(StateContext context);
}
/*
Context class which will handle the state change and delegate event to appropriate event handler of current state
*/
Class StateContext {
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private State currentState = null;
StateContext() {
currentState = new State1();
}
//Handle event1 and pass it to the appropriate event handler for the current state.
public void handleEvent1() {
currentState.handleEvent1();
}
.
.
.
//Handle event5 and pass it to the appropriate event handler for the current state.
public void handleEvent5() {
currentState.handleEvent5();
}
// Method to change the state.
// This method will be called by each state when it needs to transit to a new state.
public void changeState(State newState) {
accquireLock();
currentState.exit();
currentState = newState;
currentState.enter();
}
// Release read lock and accquire write lock
public void accquireLock() {
lock.readLock().unlock()
lock.writeLock().lock();
}
// accquire readlock and release write lock
public void releaseLock() {
lock.readLock().lock()
lock.writeLock().unlock();
}
}
爲了簡單起見,我提供了只有一個狀態的實現。
public class State1 implements State {
public void handleEvent1(StateContext context) {
//Hand1e Event 1
}
.
.
.
public void handleEvent5(StateContext context) {
//Handle Event 5
}
public void enter(StateContext context) {
//Release the lock here
context.releaseLock();
/*Here is my question. Is it a good java practice to expose accquire and release lock in Context object. And use the exposed method here to release lock.
*/
// Do some action on entering the state. This may take few seconds to finish
}
}
我想在進入狀態後才能釋放鎖。我也不想鎖定,直到enter()結束。如果我持有鎖直到輸入完成,我不能處理其他事件,並且它可能會超時。對於某些事件(它並不真正改變狀態),我們需要讀取狀態並根據狀態來處理它們或別理他們。如果我沒有釋放鎖定,它們將不能被處理。另外在其他一些情況下,如果一個事件發生關閉(這個事件改變了狀態),當enter()正在進行時,狀態機將無法處理它。我必須立即關閉狀態機,因爲在關機事件發生後繼續輸入()不適合。
我的問題: 這是一個很好的java編程實踐,將accquireLock和releaseLock公開爲Context類中的API並在每個狀態類中使用它們。
感謝, 阿倫
爲什麼在代碼在你的'changeState()'方法中執行後你不調用'releaseLock()'?既然你在該方法開始時獲得了鎖,那麼在它的最後釋放鎖似乎是一致的設計,不是嗎? – Deactivator2
對於我的應用程序,如果我在enter()進行時收到關閉機器的關機事件,我不應該繼續輸入()。繼續可能會導致不利影響,或者可能不會導致任何結果,除非浪費資源直到enter()結束。在某些情況下,輸入可能需要超過5分鐘,併發送很多請求。如果我繼續請求,可能無法到達接收方,或者接收方可能會丟棄我的請求,我應該立即停止並轉到初始狀態(爲此我需要鎖定)。 – Arun
然後,你需要的是一種中斷狀態的'enter'方法的方法,它超越了你已有的任何鎖定。將鎖對象視爲狀態更改的塊,但關閉事件優於任何狀態更改事件,因此應該能夠隨時生效。 – Deactivator2