Máquina de estado basada en enumeración Java (FSM): paso de eventos
Estoy usando varias máquinas de estado basadas en enumeraciones en mi aplicación de Android. Si bien estos funcionan muy bien, lo que estoy buscando es una sugerencia sobre cómo recibir eventos con elegancia, generalmente de devoluciones de llamada registradas o de mensajes de bus de eventos, en el estado actualmente activo. De los muchos blogs y tutoriales sobre FSM basados en enumeración, la mayoría de ellos dan ejemplos de máquinas de estado que consumen datos (por ejemplo, analizadores) en lugar de mostrar cómo estos FSM pueden ser impulsados por eventos.
Una máquina de estado típica que estoy usando tiene esta forma:
private State mState;
public enum State {
SOME_STATE {
init() {
...
}
process() {
...
}
},
ANOTHER_STATE {
init() {
...
}
process() {
...
}
}
}
...
En mi situación, algunos de los estados desencadenan un trabajo que se debe hacer en un objeto en particular, registrando un oyente. Ese objeto devuelve la llamada de forma asíncrona cuando se realiza el trabajo. En otras palabras, solo una simple interfaz de devolución de llamada.
Del mismo modo, tengo un EventBus. Las clases que desean recibir notificaciones de eventos nuevamente implementan una interfaz de devolución de llamada ylisten()
para esos tipos de eventos en EventBus.
Por lo tanto, el problema básico es que la máquina de estados, o sus estados individuales, o la clase que contiene la enumeración FSM, oalguna cosa tiene que implementar esas interfaces de devolución de llamada, para que puedan representar eventos en el estado actual.
Un enfoque que he usado es para todoenum
para implementar las interfaces de devolución de llamada. La enumeración en sí tiene implementaciones predeterminadas de los métodos de devolución de llamada en la parte inferior, y los estados individuales pueden anular esos métodos de devolución de llamada para los eventos que les interesan. Para que esto funcione, cada estado debe registrarse y anular el registro a medida que entra y sale, de lo contrario existe el riesgo de que ocurra la devolución de llamada en un estado que no sea el estado actual. Probablemente me quedaré con esto si no encuentro nada mejor.
Otra forma es que la clase que contiene implemente las devoluciones de llamada. Luego tiene que delegar esos eventos en la máquina de estado, llamandomState.process( event )
. Eso significa que necesitaría enumerar tipos de eventos. Por ejemplo:
enum Events {
SOMETHING_HAPPENED,
...
}
...
onSometingHappened() {
mState.process( SOMETHING_HAPPENED );
}
Sin embargo, no me gusta porque (a) tendría la fealdad de necesitarswitch
en los tipos de eventos dentro delprocess(event)
de cada estado, y (b) pasar parámetros adicionales parece incómodo.
Me gustaría una sugerencia para una solución elegante para esto sin recurrir al uso de una biblioteca.