我正在为我的应用程序在Java中实现一个状态模式,并且几乎不需要澄清。
状态机有状态1到状态5的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编程实践。
谢谢, 阿伦
答案 0 :(得分:0)
要回答这个问题,如果锁由状态“manager”类保存,那么该类应该是控制锁访问的类,而不是任何实际的状态类。
关于在enter
完成之前持有锁的声明,这正是锁定点:您不希望其他方法涉及或中断。相反,您应该开发某种事件队列来捕获所有事件,并在接收对象繁忙时等待分发它们。要么是这样,要么为你知道要中断的事件做一个特定的例外,这样你就可以在指定的事件被触发时绕过锁定。
如果您选择使用中断方法,则必须在每个State
类的enter
方法中实施一些检查,以检查是否已触发关闭事件。我认为它工作的唯一另一种方法是使每个State
扩展Thread
,以便您可以随意中断/停止它,尽管在这种情况下听起来不像是一个有效的选项。