¿Alguien puede explicar en términos simples?
Los patrones de diseño no son realmente conceptos "laicos", pero trataré de hacerlo lo más claro posible. Cualquier patrón de diseño puede considerarse en tres dimensiones:
- El problema que resuelve el patrón;
- La estructura estática del patrón (diagrama de clase);
- La dinámica del patrón (diagramas de secuencia).
Comparemos Estado y Estrategia.
Problema que resuelve el patrón
El estado se usa en uno de dos casos [GoF book p. 306] :
- El comportamiento de un objeto depende de su estado, y debe cambiar su comportamiento en tiempo de ejecución dependiendo de ese estado.
- Las operaciones tienen grandes declaraciones condicionales multiparte que dependen del estado del objeto. Este estado generalmente está representado por una o más constantes enumeradas. A menudo, varias operaciones contendrán esta misma estructura condicional. El patrón de estado coloca cada rama del condicional en una clase separada. Esto le permite tratar el estado del objeto como un objeto en sí mismo que puede variar independientemente de otros objetos.
Si desea asegurarse de que realmente tiene el problema que resuelve el patrón de estado, debería poder modelar los estados del objeto utilizando una máquina de estados finitos . Puede encontrar un ejemplo aplicado aquí .
Cada transición de estado es un método en la interfaz de estado. Esto implica que para un diseño, debe estar bastante seguro acerca de las transiciones de estado antes de aplicar este patrón. De lo contrario, si agrega o elimina transiciones, será necesario cambiar la interfaz y todas las clases que la implementan.
Personalmente no he encontrado este patrón tan útil. Siempre puede implementar máquinas de estados finitos utilizando una tabla de búsqueda (no es una forma OO, pero funciona bastante bien).
La estrategia se utiliza para el siguiente [Libro de GoF p. 316] :
- Muchas clases relacionadas difieren solo en su comportamiento. Las estrategias proporcionan una forma de configurar una clase con uno de los muchos comportamientos.
- Necesita diferentes variantes de un algoritmo. Por ejemplo, puede definir algoritmos que reflejen diferentes compensaciones espacio / tiempo. Las estrategias se pueden utilizar cuando estas variantes se implementan como una jerarquía de algoritmos de clase [HO87].
- un algoritmo usa datos que los clientes no deberían conocer. Use el patrón de estrategia para evitar exponer estructuras de datos complejas y específicas de algoritmos.
- una clase define muchos comportamientos, y estos aparecen como múltiples declaraciones condicionales en sus operaciones. En lugar de muchos condicionales, mueva ramas condicionales relacionadas a su propia clase de estrategia.
El último caso de dónde aplicar la Estrategia está relacionado con una refactorización conocida como Reemplazar condicional por polimorfismo .
Resumen: Estado y Estrategia resuelven problemas muy diferentes. Si su problema no se puede modelar con una máquina de estados finitos, entonces el patrón de estado probable no es apropiado. Si su problema no se trata de encapsular variantes de un algoritmo complejo, entonces la Estrategia no se aplica.
Estructura estática del patrón
Estado tiene la siguiente estructura de clases UML:
La estrategia tiene la siguiente estructura de clases UML:
Resumen: en términos de estructura estática, estos dos patrones son en su mayoría idénticos. De hecho, las herramientas de detección de patrones como esta consideran que " la estructura de los patrones [...] es idéntica, prohibiendo su distinción por un proceso automático (por ejemplo, sin referirse a información conceptual) " .
Sin embargo, puede haber una diferencia importante si ConcreteStates decide por sí mismo las transiciones de estado (consulte las asociaciones " podría determinar " en el diagrama anterior). Esto da como resultado el acoplamiento entre estados concretos. Por ejemplo (vea la siguiente sección), el estado A determina la transición al estado B. Si la clase Contextual decide la transición al siguiente estado concreto, estas dependencias desaparecen.
Dinámica del patrón.
Como se mencionó en la sección Problema anterior, Estado implica que el comportamiento cambia en tiempo de ejecución dependiendo de algún estado de un objeto. Por lo tanto, se aplica la noción de transición de estado , como se discutió con la relación de la máquina de estados finitos . [GoF] menciona que las transiciones pueden definirse en las subclases de ConcreteState o en una ubicación centralizada (como una ubicación basada en tablas).
Supongamos una máquina de estados finitos simple:
Suponiendo que las subclases deciden la transición de estado (al devolver el siguiente objeto de estado), la dinámica se ve así:
Para mostrar la dinámica de la estrategia , es útil tomar prestado un ejemplo real .
Resumen : cada patrón utiliza una llamada polimórfica para hacer algo según el contexto. En el patrón de estado, la llamada polimórfica (transición) a menudo causa un cambio en el siguiente estado . En el patrón de estrategia, la llamada polimórfica no suele cambiar el contexto (por ejemplo, pagar con tarjeta de crédito una vez no implica que pagará con PayPal la próxima vez). Nuevamente, la dinámica del patrón de estado está determinada por su correspondiente máquina de estado fininte, que (para mí) es esencial para corregir la aplicación de este patrón.