En determinadas ocasiones se requiere que un objeto tenga diferentes comportamientos según el estado en que se encuentra. Esto resulta complicado de manejar, sobretodo cuando se debe tener en cuenta el cambio de comportamientos y estados de dicho objeto, todos dentro del mismo bloque de código. El patrón State propone una solución a esta complicación, creando un objeto por cada estado posible.
Este patrón debe ser utilizado cuando:
- El comportamiento de un objeto depende de un estado, y debe cambiar en tiempo de ejecución según el comportamiento del estado.
- Cuando las operaciones tienen largas sentencias con múltiples ramas que depende del estado del objeto.
Diagrama UML
Context: mantiene una instancia con el estado actual
State: define interfaz para el comportamiento asociado a un determinado estado del Contexto.
StateConcreto: cada subclase implementa el comportamiento asociado con un estado del contexto.
El Context delega el estado específico al objeto StateConcreto actual. Un objeto Context puede pasarse a sí mismo como parámetro hacia un objeto State. De esta manera la clase State puede acceder al contexto si fuese necesario. Context es la interfaz principal para el cliente. El cliente puede configurar un contexto con los objetos State. Una vez hecho esto estos clientes no tendrán que tratar con los objetos State directamente. Tanto el objeto Context como los objetos de StateConcreto pueden decidir el cambio de estado.
Ejemplo
Imaginemos que vamos a un banco y cuando llegamos nos colocamos en la fila de mostrador: si la misma esta abierta, seguiremos en la fila. En cambio, si esta cerrada nos colocaremos en otra fila o tomaremos alguna decisión acorde. Por otro lado, si vemos un cartel que dice "enseguida vuelvo" quizás tenemos que contemplar el tiempo disponible que tenemos. Es decir, para nosotros, el comportamiento de un banco cambia radicalmente según el estado en el que se encuentre. Para estas ocasiones, es ideal el uso de un patrón de estados.
El banco publica un método llamado atende() pero en realidad la atención la realiza la ventanilla.
La ventanilla cambia su comportamiento según el estado en que se encuentre. Por ejemplo, si esta cerrada, no hay atención directamente. Por eso mismo, delega el método de atención a su estado y es este mismo estado quién toma la decisión de atender o no.
Consecuencias
- Se localizan fácilmente las responsabilidades de los estados concretos, dado que se encuentran en las clases que corresponden a cada estado. Esto brinda una mayor claridad en el desarrollo y el mantenimiento posterior. Esta facilidad la brinda el hecho que los diferentes estados están representados por un único atributo (state) y no envueltos en diferentes variables y grandes condicionales.
- Hace los cambios de estado explícitos puesto que en otros tipos de implementación los estados se cambian modificando valores en variables, mientras que aquí al estar representado cada estado.
- Facilita la ampliación de estados mediante una simple herencia, sin afectar al Context.
- Permite a un objeto cambiar de estado en tiempo de ejecución.
- Los estados pueden reutilizarse: varios Context pueden utilizar los mismos estados.
- Se incrementa el número de subclases.
Temas a tener en cuenta
El patrón no indica exactamente dónde definir las transiciones de un estado a otro. Existen dos formas de solucionar esto: definiendo estas transiciones dentro de la clase contexto, la otra es definiendo estas transiciones en las subclaes de State. Es más conveniente utilizar la primer solución cuando el criterio a aplicar es fijo, es decir, no se modificará. En cambio la segunda resulta conveniente cuando este criterio es dinámico, el inconveniente aquí se presenta en la dependencia de código entre las subclases.
Por otro lado, los estados concretos suelen ser Singleton.
8 comentarios:
y el metodo main capo??
Tenes razon, me lo comi! Agregado, gracias!
Sos un groso! Gracias!!
me da un error en la salida del main.. subime tu programa
Formatie la pc hace mucho y no lo tengo mas, copiame el error x aca por favor. Saludos!
muchas gracias me sirvio mucho para una tarea!!!
Yo como persona4 habria puesto = newPersona("Ivael","Tercero",0912)
Es verdad lo de persona4, pero no creo que lo cambie, este señor debe estar muerto como su club...
Publicar un comentario