Java enum-based state machine (FSM): transmitindo eventos
Estou usando várias máquinas de estado baseadas em enum no meu aplicativo Android. Embora funcionem muito bem, o que estou procurando é uma sugestão de como receber eventos com elegância, normalmente de retornos de chamada registrados ou de mensagens de barramento de eventos, para o estado ativo no momento. Dos muitos blogs e tutoriais sobre FSMs baseados em enum, a maioria deles fornece exemplos de máquinas de estado que consomem dados (por exemplo, analisadores) em vez de mostrar como esses FSMs podem ser direcionados a eventos.
Uma máquina de estado típica que estou usando tem este formato:
private State mState;
public enum State {
SOME_STATE {
init() {
...
}
process() {
...
}
},
ANOTHER_STATE {
init() {
...
}
process() {
...
}
}
}
...
Na minha situação, alguns dos estados acionam um trabalho a ser feito em um objeto específico, registrando um ouvinte. Esse objeto chama de forma assíncrona quando o trabalho é concluído. Em outras palavras, apenas uma interface simples de retorno de chamada.
Da mesma forma, eu tenho um EventBus. As classes que desejam ser notificadas de eventos novamente implementam uma interface de retorno de chamada elisten()
para esses tipos de evento no EventBus.
O problema básico, portanto, é que a máquina de estados, ou seus estados individuais, ou a classe que contém o FSM da enumeração, oualguma coisa precisa implementar essas interfaces de retorno de chamada, para que elas possam representar eventos no estado atual.
Uma abordagem que usei é para toda aenum
para implementar a (s) interface (s) de retorno de chamada. A enum em si possui implementações padrão dos métodos de retorno de chamada na parte inferior, e os estados individuais podem substituir esses métodos pelos eventos nos quais estão interessados. Para que isso funcione, cada estado deve registrar e cancelar o registro à medida que entra e sai, caso contrário existe o risco de o retorno de chamada ocorrer em um estado que não é o estado atual. Provavelmente vou ficar com isso se não encontrar nada melhor.
Outra maneira é a classe que contém implementar os retornos de chamada. Em seguida, ele deve delegar esses eventos na máquina de estado, chamandomState.process( event )
. Isso significa que eu precisaria enumerar os tipos de eventos. Por exemplo:
enum Events {
SOMETHING_HAPPENED,
...
}
...
onSometingHappened() {
mState.process( SOMETHING_HAPPENED );
}
No entanto, não gosto disso porque (a) eu teria a feia necessidade deswitch
nos tipos de eventos dentro doprocess(event)
de cada estado e (b) passar por parâmetros adicionais parece estranho.
Gostaria de sugerir uma solução elegante para isso sem recorrer ao uso de uma biblioteca.