我正在Java中为我的应用程序实现状态模式,并需要一些澄清。
状态机有5个状态:State 1到State 5。 共有5个事件(Event1到Event5)会导致状态转移。 并非所有事件都适用于所有状态。如果在特定状态下不适用该事件,则应用程序将抛出异常。
当状态机初始化后,它从state1开始。
以下是接口和上下文类。
为了简单起见,我只提供了一个状态的实现。
我希望只在进入状态后才释放锁。同时,我不想一直持有锁直到enter()函数结束,因为如果我在enter()函数完成之前一直持有锁,我就不能处理其他事件,而且可能会超时。对于一些不真正改变状态的事件,我们需要读取状态并根据状态进行处理或忽略它们。如果我不释放锁,它们就无法被处理。另外,在一些情况下,如果在进入状态时发生了关机事件(该事件会改变状态),则无法处理状态机。在这种情况下,我必须立即关闭状态机,因为在关机事件发生后继续执行enter()函数是不合适的。
我的问题是: 将accquireLock和releaseLock公开作为Context类的API并在每个状态类中使用它们是否是良好的Java编程实践?
谢谢, Arun
状态机有5个状态:State 1到State 5。 共有5个事件(Event1到Event5)会导致状态转移。 并非所有事件都适用于所有状态。如果在特定状态下不适用该事件,则应用程序将抛出异常。
当状态机初始化后,它从state1开始。
以下是接口和上下文类。
/*
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()函数完成之前一直持有锁,我就不能处理其他事件,而且可能会超时。对于一些不真正改变状态的事件,我们需要读取状态并根据状态进行处理或忽略它们。如果我不释放锁,它们就无法被处理。另外,在一些情况下,如果在进入状态时发生了关机事件(该事件会改变状态),则无法处理状态机。在这种情况下,我必须立即关闭状态机,因为在关机事件发生后继续执行enter()函数是不合适的。
我的问题是: 将accquireLock和releaseLock公开作为Context类的API并在每个状态类中使用它们是否是良好的Java编程实践?
谢谢, Arun
changeState()
方法执行完毕后不调用releaseLock()
呢?既然您在该方法的开头获取了锁,那么在方法结束时释放锁似乎是一致的设计,不是吗? - Deactivator2StateContext
类中创建一个方法,用于接收关闭事件。在基础的State
类中创建另一个方法,该方法将从第一个方法中调用,并将每个State
类中的interrupted
布尔值设置为true。然后,在每个State
的enter()
功能块代码之后,检查interrupted
布尔值是否为true,如果是,则退出该方法。 - Deactivator2