Patrón State – Videotutorial

En esta entrega vamos a abordar en profundidad uno de los patrones GoF más utilizados, el patrón Estado o State. Pero antes de entrar a analizar los detalles del patrón debemos preguntarnos que se entiende en si por estado. Un sinónimo bastante próximo a lo que se entiende por estado es memoria. Y en lo que se refiere a memoria, en el caso de un programa, este es el terreno de las variables en general: campos, variables, argumentos de entrada, etc. De ahí que podamos decir que el estado de un programa en un momento dado sea el valor de todas y cada una de la variables del programa; del mismo modo, el estado de un objeto sería el valor que toman en un momento dado todas sus «variables», es decir, sus campos de instancia.

Sabemos que en un lenguaje como java, diseñado para favorecer la programación mediante el paradigma de la orientación a objetos, la clase es la entidad de nivel superior que encapsula al resto de miembros.
Estos miembros pueden representar datos (información), los llamados campos, o pueden representar comportamiento, los llamados métodos (encapsulando una serie de instrucciones).

Conocemos tambien que en lo que respecta a campos de una clase, cuyo papel como hemos dicho es almacenar información en memoria, algunos pueden ser compartidos por todas las instancias de la clase o estaticos, mientras para otros cada instancia tiene su propia versión o copia del campo, los campos de instancia.

Dicho todo esto, si en una clase, nada más se define comportamiento, es decir, sus miembros son únicamente métodos, entonces, este objeto carece de estado. Y esto tiene una implicación práctica muy importante. Por un lado, no importa cuantas veces se llame a un mismo método de ese objeto, si los argumentos de llamada son los mismos el resultado o comportamiento será siempre el mismo. Por otro lado, dará igual también el orden en el que se llame a los métodos de ese objeto porque su comportamiento no depende de si se ha llamado a otro método previamente. Como no hay campos de instancia, el objeto carece de estado, y sin estado «no hay memoria sobre el pasado».

Por tanto, cuando hablamos de estado, nos estamos refiriendo al valor que contienen en un momento dado los campos de una clase. Si el ámbito de estos campos ha sido declarado privado (como preconizan las buenas prácticas de la POO), entonces la única forma de modificar el valor de alguno de estos campos del objeto es mediante la llamada a alguno de sus métodos, siendo el caso más característico de todos ellos un método «setter».

En este punto, llegamos al caso de que algún método de la clase quiera asegurarse de que se ha llamado previamente a algún otro método, cosa que podrá averiguar indirectamente comprobando el valor de algún campo del objeto, o dicho de otra forma, comprobando el estado del objeto.

La necesidad de comprobar el estado del objeto es un hecho bastante común en programación, puesto que muchas veces para poder llevar a cabo su labor el método invocado necesita estar seguro de que se cumplen unas determinadas precondiciones, ya que de no ser asi, puede no tener sentido realizar su trabajo. Y aqui está «la madre del cordero». La comprobación de que se cumplen estas precondiciones, a partir de analizar el valor de los campos que sea necesario comprobar, puede requirir el uso de estructuras condicionales, cuyo nivel de anidamiento y ramificaciones hagan muy complicado seguir la pista de la lógica de esas instrucciones. Estas bifurcaciones, si bien pueden compilar sin errores de sintaxis pueden no estar haciendo lo correcto desde un punto de vista semántico, en cada combinación de valores posible que puedan tomar los campos del objeto, el estado.
Ademas de esto, es posible que una de estas precondiciones pueda ser necesario comprobarla en mas de un método, lo cual conlleva copiar y pegar la expresión condicional y/o ramificaciones idénticas en más de un sitio del código. Bienvenidos a la pesadilla del mantenimiento del código!!!!

Existen técnicas alternativas más eficientes, en base a constatar que básicamente lo que estamos haciendo es seguir la pista a algunas de las combinaciones de valores que pueden tomar algunos de los campos del objeto. Cuando se da alguna combinación de estas decimos que el objeto se encuentra en el estado X, si se da otra de estas combinaciones diremos que su estado es Y, etc.

Llegados a este punto es posible que tengamos un número finito de estados. En este caso, estamos ante lo que se conoce como una máquina de estados finita o FSM. Nuestra objeto, por tanto, no es más que una máquina de estados finita, y la podremos programar siguiendo algunas de las técnicas para implementar una FSM. Entre todas las diferentes técnicas que existen, la que mejor saca partido de la POO es precisamente la que consiste en aplicar el patrón State. Por ello, podemos decir que el patrón State no es más que la implementación de una FSM mediante el uso de la POO.

Aqui teneis el videotutorial sobre el patrón de diseño State.