Конечный автомат на основе перечислений Java (FSM): передача событий

Я использую несколько конечных автоматов на основе enum в своем приложении для Android. Хотя они работают очень хорошо, я ищу предложение о том, как элегантно получать события, обычно из зарегистрированных обратных вызовов или сообщений Eventbus, в текущее активное состояние. Из многих блогов и учебных пособий, касающихся FSM на основе перечисления, большинство из них приводят примеры конечных автоматов, которые потребляют данные (например, анализаторы), а не показывают, как эти FSM могут управляться событиями.

Типичный конечный автомат, который я использую, имеет такую ​​форму:

private State mState;

public enum State {

    SOME_STATE {


        init() {
         ... 
        }


        process() {
         ... 
        }


    },


    ANOTHER_STATE {

        init() {
         ... 
        }

        process() {
         ... 
        }

    }

}

...

В моей ситуации некоторые состояния запускают часть работы над конкретным объектом, регистрируя слушателя. Этот объект асинхронно перезванивает, когда работа завершена. Другими словами, просто интерфейс обратного вызова.

Точно так же у меня есть EventBus. Классы, желающие получать уведомления о событиях, снова реализуют интерфейс обратного вызова иlisten() для тех типов событий на EventBus.

Следовательно, основная проблема заключается в том, что конечный автомат, или его отдельные состояния, или класс, содержащий перечисление FSM, иличто-то должен реализовать эти интерфейсы обратного вызова, чтобы они могли представлять события в текущем состоянии.

Один подход, который я использовал для всегоenum реализовать интерфейс (ы) обратного вызова. У самого перечисления внизу есть реализации по умолчанию методов обратного вызова, и отдельные состояния могут затем переопределять эти методы обратного вызова для событий, в которых они заинтересованы. Чтобы это работало, каждое состояние должно регистрироваться и отменяться при входе и выходе, в противном случае существует риск обратного вызова в состоянии, которое не является текущим. Я, вероятно, буду придерживаться этого, если не найду ничего лучшего.

Другой способ - для содержащего класса реализовать обратные вызовы. Затем он должен делегировать эти события на конечный автомат, вызываяmState.process( event ), Это означает, что мне нужно будет перечислять типы событий. Например:

enum Events {
    SOMETHING_HAPPENED,
    ...
}

...

onSometingHappened() {

    mState.process( SOMETHING_HAPPENED );
}

Однако мне это не нравится, потому что (а) у меня было бы уродство необходимостиswitch на типах событий в пределахprocess(event) каждого состояния, и (б) прохождение через дополнительные параметры выглядит неловко.

Я хотел бы предложить элегантное решение для этого, не прибегая к использованию библиотеки.

Ответы на вопрос(7)

Ваш ответ на вопрос