Я реализую шаблон состояния в Java для своего приложения и нуждаюсь в нескольких разъяснениях.
Конечный автомат имеет 5 состояний от состояния 1 до состояния 5. Всего 5 событий (от события 1 до события 5), которые вызывают переход состояния. Не все события применимы во всех штатах. Если событие неприменимо в этом конкретном состоянии, приложение выдаст исключение.
Когда конечный автомат инициализируется, он начинается с 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
}
}
Я хочу снять блокировку только после входа в состояние. Также я не хочу удерживать блокировку до завершения ввода(). Если я удерживаю блокировку до завершения ввода, я не могу обрабатывать другие события, и это может быть тайм-аут. Для некоторых событий (которые на самом деле не меняют состояние) нам нужно прочитать состояние, и на основе состояния мы можем их обработать или игнорируй их. Если я не снимаю блокировку, они не могут быть обработаны. Также в некоторых других случаях, если событие завершается (это событие меняет состояние), конечный автомат во время ввода () не может его обработать. Я должен немедленно выключить конечный автомат, поскольку продолжение ввода() после того, как наступило событие выключения, нецелесообразно.
Мой вопрос: является ли хорошей практикой программирования java выставлять accquireLock и releaseLock как API в классе Context и использовать их в каждом классе состояния.
Спасибо, Арун
releaseLock()
после выполнения кода в вашем методеchangeState()
? Поскольку вы получаете блокировку в начале этого метода, казалось бы, логично разблокировать блокировку в конце, не так ли? - person Deactivator2   schedule 07.08.2013enter
состояния, который превосходит любую имеющуюся у вас блокировку. Рассматривайте объект блокировки как блок для изменения состояния, но событие выключения важнее любого события изменения состояния и, следовательно, должно иметь возможность вступить в силу в любое время. - person Deactivator2   schedule 07.08.2013StateContext
метод, который будет получать события выключения. Создайте метод в базовом классеState
, который будет вызываться из первого метода, который установит логическое значениеinterrupted
в каждом классеState
в значение true. Затем, после каждого функционального блока кода в каждомState
enter()
, выполнить проверку логического значенияinterrupted
и выйти из метода, если оно истинно. - person Deactivator2   schedule 07.08.2013