🗽 State
Introducción
El patrón State es un patrón de diseño de comportamiento que permite a un objeto cambiar su comportamiento cuando su estado interno cambia. Parece como si el objeto cambiara su clase. Es especialmente útil en el diseño de máquinas de estado, donde el comportamiento de un objeto puede cambiar drásticamente dependiendo de su estado actual.
Intención
El propósito del patrón State es encapsular los estados variables de un objeto en clases separadas y permitir al objeto cambiar de estado como si cambiara de clase. En lugar de estar lleno de condicionales para realizar diferentes acciones dependiendo del estado, el objeto delega las acciones al objeto de estado actual.
Uso
El patrón State es útil cuando tienes un objeto que se comporta de manera diferente según el estado en el que se encuentra, y hay muchas operaciones condicionales que dependen del estado.
Estructura
El patrón State se compone de varias partes clave:
-
Contexto (Context):
- Es la clase que tiene un estado que dicta cómo debe comportarse. Mantiene una referencia a una instancia de una subclase de
State
que representa el estado actual. - El contexto delega las operaciones a la instancia de
State
para actuar de acuerdo con su estado actual.
- Es la clase que tiene un estado que dicta cómo debe comportarse. Mantiene una referencia a una instancia de una subclase de
-
Estado (State):
- Es una interfaz o clase abstracta que define la interfaz para encapsular el comportamiento asociado con un estado particular del contexto.
- Puede definir métodos que serán llamados por el contexto para realizar acciones que dependen del estado.
-
Estados Concretos (ConcreteStates):
- Son clases que implementan la interfaz
State
y definen el comportamiento real asociado con un estado del contexto. - Cada
ConcreteState
sabe a qué otro estado debe cambiar el contexto bajo ciertas condiciones y puede realizar la transición al cambiar la referencia deState
en el contexto.
- Son clases que implementan la interfaz
Ventajas
- Localización del Comportamiento de Estado: Centraliza el comportamiento de cada estado en clases correspondientes.
- Cambios de Estado explícitos: Cambiar de un estado a otro se hace explícitamente cambiando la instancia de estado dentro del contexto, lo cual es más claro que usar múltiples condicionales.
- Estado y Transiciones Encapsulados: Al aislar los estados en diferentes clases, se encapsulan tanto las acciones como las transiciones entre estados.
Desventajas
- Aumento de Clases: Puede incrementar el número de clases en el sistema.
- Dependencia entre Estados Concretos: Puede haber dependencia entre
ConcreteStates
si no se planifica adecuadamente, lo que puede llevar a un mantenimiento más difícil.
Ejemplo Aplicado
Un ejemplo común del patrón State es una máquina expendedora que tiene diferentes estados, como ‘Esperando selección’, ‘Validando pago’, ‘Dispensando producto’, y ‘Dando cambio’. Cada estado determinará cómo responderá la máquina a diferentes entradas, como la selección de un producto o la inserción de dinero.
Resumen
El patrón State es esencial para situaciones donde el comportamiento de un objeto depende de su estado, y hay complejas reglas de transición entre estados. Este patrón oculta las complejidades de estado y transición en un marco de trabajo que es fácil de entender y mantener.
Estructura
Este diagrama UML describe el patrón de diseño State. A continuación, te detallo cada componente del diagrama y cómo interactúan entre sí:
-
Contexto (Context):
- La clase
Context
mantiene una referencia a una instancia de la claseState
, que representa el estado actual del contexto. - Contiene un método
request()
que es el punto de entrada para solicitar la operación. Este método luego delega la ejecución a la instancia deState
actual llamando astate.handle()
. - La asociación entre
Context
yState
se muestra con una línea que tiene un círculo al final, indicando queContext
mantiene una referencia aState
.
- La clase
-
Estado (State):
- La interfaz o clase abstracta
State
define un métodohandle()
, que será implementado por las subclases concretas para realizar las acciones asociadas con un estado específico. - Esta es la interfaz común que todas las clases concretas de estado implementarán.
- La interfaz o clase abstracta
-
Estados Concretos (ConcreteStateA y ConcreteStateB):
ConcreteStateA
yConcreteStateB
son implementaciones de la interfazState
. Cada una define una versión del métodohandle()
, que contiene la lógica específica que debe ejecutarse cuando el objetoContext
se encuentra en el estado correspondiente.- Estos objetos de estado concreto pueden cambiar el estado del
Context
al reemplazar la instancia de estado actual por otra, lo que permite cambiar el comportamiento delContext
dinámicamente.
-
Transiciones de Estado:
- En la práctica, la implementación de
handle()
enConcreteStateA
podría resultar en un cambio de estado al establecer una nueva instancia deState
(por ejemplo,ConcreteStateB
) en elContext
. Esto no se muestra explícitamente en el diagrama, pero es parte central de cómo funciona el patrón State.
- En la práctica, la implementación de
Cómo Funciona
- Cuando un cliente invoca
request()
en elContext
, elContext
delega esa solicitud a su objeto de estado actual llamando astate.handle()
. - El objeto de
State
actual determina qué operaciones realizar y puede cambiar el estado actual delContext
a otro estado, influyendo así en el comportamiento futuro delContext
. - Este patrón permite al
Context
cambiar su comportamiento en tiempo de ejecución sin tener que recurrir a grandes cantidades de condicionales y sin violar el principio de abierto/cerrado, que promueve que las entidades (clases, módulos, funciones, etc.) deberían estar abiertas para su extensión, pero cerradas para su modificación.
El diagrama ilustra una estructura flexible que soporta cambios en el comportamiento de un objeto sin recurrir a múltiples sentencias if
o switch
a lo largo del código, facilitando así la mantenibilidad y escalabilidad.
State vs Strategy
El patrón State y el patrón Strategy son a menudo confundidos debido a que su estructura UML puede parecer similar y ambos patrones implican el uso de composición para cambiar el comportamiento de un objeto en tiempo de ejecución. Sin embargo, sus intenciones, uso y forma de gestionar el cambio de comportamiento son distintos.
State
El patrón State se utiliza cuando el comportamiento de un objeto debe cambiar de acuerdo con su estado interno. Cada estado es representado por una clase concreta que implementa una interfaz común, y el objeto cambia su comportamiento cambiando su estado interno a diferentes instancias de estas clases de estado.
Características del State:
- Encapsula los posibles estados en diferentes clases.
- Cambios de estado normalmente se ocultan dentro de las clases de estado y pueden ser automáticos en respuesta a eventos internos.
- El objeto de contexto puede no saber qué clase de estado concreto está en uso, reflejando un cambio en el comportamiento de manera transparente.
- El número y naturaleza de los estados pueden ser muchos y complejos, cada estado puede tener su propia lógica para determinar a qué estado cambiar después.
- Se enfoca en el ciclo de vida de un objeto y cómo cambia su comportamiento a lo largo del tiempo y los eventos internos.
Strategy
El patrón Strategy se centra en definir una familia de algoritmos, encapsulando cada uno en su propia clase de estrategia, y haciendo los algoritmos intercambiables desde el contexto. Este patrón se utiliza principalmente para seleccionar un algoritmo de un grupo de algoritmos en tiempo de ejecución.
Características del Strategy:
- Encapsula un algoritmo o estrategia específica en una clase.
- Los cambios de estrategia suelen ser explícitos y controlados desde afuera, por el cliente del objeto de contexto.
- El objeto de contexto sabe qué estrategia está utilizando y normalmente elige entre estrategias concretas predefinidas.
- Los algoritmos no suelen cambiar automáticamente y no dependen del estado interno del objeto.
- Se enfoca en operaciones o acciones que realiza el objeto y en cómo pueden variar independientemente del ciclo de vida del objeto.
Comparación
- Cambios de Comportamiento: En el State, los cambios de comportamiento están ligados al estado interno del objeto. En el Strategy, los cambios de comportamiento se realizan cambiando la estrategia asignada al objeto desde el exterior.
- Conocimiento de los Estados/Algoritmos: En el State, el objeto no necesita tener conocimiento de qué estado está activo. En Strategy, el cliente del contexto debe conocer las estrategias concretas para elegir una.
- Control de Cambios: En State, los estados suelen controlarse y cambiar desde el interior de la clase de estado. En Strategy, el contexto o el cliente externo controla cuál estrategia se utiliza.
En Resumen
El State se ocupa de lo que un objeto es (estado interno), mientras que el Strategy se ocupa de lo que un objeto hace (comportamiento o algoritmo). Mientras que State puede conducir a un cambio en el comportamiento debido a un cambio en el estado interno del objeto, Strategy implica cambiar el comportamiento asignando un nuevo algoritmo, a menudo como resultado de decisiones tomadas fuera del objeto.