¿Cuál es la diferencia entre el patrón de diseño de estrategia y el patrón de diseño de estado?

219

¿Cuáles son las diferencias entre el patrón de diseño de la Estrategia y el patrón de diseño del Estado? Estaba leyendo bastantes artículos en la web, pero no pude ver la diferencia claramente.

¿Alguien puede explicar la diferencia en términos simples?

Chin Tser
fuente
Según las respuestas aquí y mis propias observaciones, parece que las implementaciones son en gran medida (aunque no del todo) las mismas. Más bien, la diferencia es principalmente una de intención: estamos tratando de adaptar el comportamiento, ya sea en base a nuestro estado (patrón de estado) o en base a otra cosa (patrón de estrategia). Muy a menudo, algo más es "lo que el cliente elige", a través de la inyección.
Timo

Respuestas:

139

Honestamente, los dos patrones son bastante similares en la práctica, y la diferencia definitoria entre ellos tiende a variar dependiendo de a quién le pregunte. Algunas opciones populares son:

  • Los estados almacenan una referencia al objeto de contexto que los contiene. Las estrategias no lo hacen.
  • Los estados pueden reemplazarse a sí mismos (IE: cambiar el estado del objeto de contexto a otra cosa), mientras que las Estrategias no.
  • Las estrategias se pasan al objeto de contexto como parámetros, mientras que los estados son creados por el objeto de contexto mismo.
  • Las estrategias solo manejan una tarea única y específica, mientras que los Estados proporcionan la implementación subyacente para todo (o casi todo) que hace el objeto de contexto.

Una implementación "clásica" coincidiría con el Estado o la Estrategia para cada elemento de la lista, pero se encuentra con híbridos que tienen mezclas de ambos. Si un particular es más Estado-y o Estrategia-y es, en última instancia, una cuestión subjetiva.


fuente
66
Si está contando al GoF como una de las opciones populares, no estarían de acuerdo con que los Estados sean necesariamente creados por el contexto (el cliente puede crearlos y pasarlos al contexto, al igual que con la Estrategia).
Will Hardwick-Smith
109
  • El patrón de estrategia se trata realmente de tener una implementación diferente que logre (básicamente) lo mismo, de modo que una implementación pueda reemplazar a la otra según lo requiera la estrategia. Por ejemplo, puede tener diferentes algoritmos de clasificación en un patrón de estrategia. Las personas que llaman al objeto no cambian según la estrategia que se esté empleando, pero independientemente de la estrategia, el objetivo es el mismo (ordenar la colección).
  • El patrón de estado se trata de hacer cosas diferentes según el estado, mientras se libera a la persona que llama de la carga de acomodar todos los estados posibles. Entonces, por ejemplo, es posible que tenga un getStatus()método que devolverá diferentes estados según el estado del objeto, pero la persona que llama al método no tiene que codificarse de manera diferente para tener en cuenta cada estado potencial.
Yishai
fuente
1
¿Pero quién cambia la estrategia en el patrón de estrategia?
Noor
1
@Noor, generalmente es un parámetro o campo de algún tipo. El código real de la persona que llama no cambia en función de un cambio en la estrategia.
Yishai
44
@Noor, sí, pero en cualquier patrón de estrategia que se me ocurra ahora, será una decisión inicial que no cambiará en el medio.
Yishai
2
Estoy con el mismo problema, Estado o Estrategia, creo que la diferencia en pocas palabras es, estado, comportamiento es autodeterminado, estrategia, comportamiento es determinado por la persona que llama.
Rene MF
1
En la aplicación de comercio electrónico, si se necesita aplicar un descuento adicional en la temporada festiva, entonces es un patrón de diseño estatal. La lógica de la tasa de descuento real se puede aplicar con el patrón de diseño de la estrategia, si hay más de una forma de llegar a ese número.
Bharathkumar V
85

La diferencia simplemente radica en que resuelven diferentes problemas:

  • El patrón de estado trata de qué (estado o tipo) es un objeto (en): encapsula el comportamiento dependiente del estado, mientras que
  • El patrón Estrategia trata de cómo un objeto realiza una determinada tarea: encapsula un algoritmo.

Sin embargo, los constructos para lograr estos diferentes objetivos son muy similares; ambos patrones son ejemplos de composición con delegación.


Algunas observaciones sobre sus ventajas:

Al utilizar el Estado patrón de la clase (contexto) de retención de estado es relevado de conocimiento de lo que el estado o tipo es y qué estados o tipos que están disponibles. Esto significa que la clase se adhiere al principio de diseño abierto-cerrado (OCP): la clase está cerrada por cambios en los estados / tipos que existen, pero los estados / tipos están abiertos a extensiones.

Al usar el patrón Estrategia , la clase que usa algoritmos (contexto) se libera del conocimiento de cómo realizar una determinada tarea (- el "algoritmo"). Este caso también crea una adherencia al OCP; la clase está cerrada por cambios con respecto a cómo realizar esta tarea, pero el diseño está muy abierto a la adición de otros algoritmos para resolver esta tarea.
Esto probablemente también mejore la adherencia de la clase de contexto al principio de responsabilidad única (SRP). Además, el algoritmo está fácilmente disponible para su reutilización por otras clases.

Ulf Åkerstedt
fuente
42

¿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:

  1. El problema que resuelve el patrón;
  2. La estructura estática del patrón (diagrama de clase);
  3. 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:

Diagrama de clase PlantUML del patrón de estado

La estrategia tiene la siguiente estructura de clases UML:

Diagrama de clase PlantUML del patrón de estrategia

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:

Diagrama de transición de estado de PlantUML con dos estados y una transición

Suponiendo que las subclases deciden la transición de estado (al devolver el siguiente objeto de estado), la dinámica se ve así:

Diagrama de secuencia PlantUML para transiciones de estado

Para mostrar la dinámica de la estrategia , es útil tomar prestado un ejemplo real .

Diagrama de secuencia PlantUML para transiciones de estrategia

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.

Fuhrmanator
fuente
Esta respuesta fue muy útil para mí para hacerme distinguir la diferencia. El argumento de la máquina de estado parece ser pertinente en mi humilde opinión. En realidad, esto resume las respuestas anteriores de una manera teórica de la informática.
medunes
Esta respuesta es muy útil, para mí esta es la mejor.
Chofoteddy
25

El Patrón de estrategia implica mover la implementación de un algoritmo de una clase de hosting y colocarlo en una clase separada. Esto significa que la clase de host no necesita proporcionar la implementación de cada algoritmo en sí mismo, lo que probablemente conduzca a un código no limpio.

Los algoritmos de clasificación generalmente se usan como ejemplo, ya que todos hacen el mismo tipo de cosas (ordenar). Si cada algoritmo de clasificación diferente se coloca en su propia clase, el cliente puede elegir fácilmente qué algoritmo usar y el patrón proporciona una manera fácil de acceder a él.

El patrón de estado implica cambiar el comportamiento de un objeto cuando cambia el estado del objeto. Esto significa que la clase de host no proporciona la implementación del comportamiento para todos los diferentes estados en los que puede estar. La clase de host generalmente encapsula una clase que proporciona la funcionalidad que se requiere en un estado dado, y cambia a una clase diferente cuando el estado cambia

Ryan Spears
fuente
16

Considere un sistema IVR (Respuesta de voz interactiva) que maneja las llamadas de los clientes. Es posible que desee programarlo para manejar clientes en:

  • Días de trabajo
  • Días festivos

Para manejar esta situación, puede usar un patrón de estado .

  • Vacaciones : IVR simplemente responde diciendo que 'Las llamadas se pueden atender solo en días hábiles entre las 9 a.m. y las 5 p.m. '.
  • Días de trabajo : responde conectando al cliente con un ejecutivo de atención al cliente.

Este proceso de conectar a un cliente con un ejecutivo de soporte puede implementarse mediante un Patrón de estrategia en el que los ejecutivos se eligen en función de:

  • Round Robin
  • Menos usado recientemente
  • Otros algoritmos basados ​​en prioridades

El patrón de estrategia decide " cómo " realizar alguna acción y el patrón de estado decide " cuándo " realizarlas.

Murali Mohan
fuente
Esta es una excelente respuesta y subestimada. Pero, sería útil mencionar por qué hay una necesidad de muchos algoritmos en su ejemplo. Por ejemplo, el algoritmo se elige según la preferencia de la compañía del centro de llamadas. También ayudaría si hubiera algoritmos más simples o triviales en su lista para aquellos que no conocen RR o LRU. Por ejemplo: el cliente de mucho tiempo tiene mayor prioridad, el cliente que más esperó tiene mayor prioridad. Gracias !
MasterJoe2
14

La estrategia representa objetos que "hacen" algo, con los mismos resultados iniciales y finales, pero internamente utilizando diferentes metodologías. En ese sentido, son análogos a representar la implementación de un verbo. El patrón de estado OTOH usa objetos que "son" algo: el estado de una operación. Si bien también pueden representar operaciones en esos datos, son más análogos a la representación de un sustantivo que a un verbo, y están diseñados para máquinas de estado.

zzzeek
fuente
11

Estrategia: la estrategia es fija y generalmente consta de varios pasos. (La clasificación constituye solo un paso y, por lo tanto, es un mal ejemplo, ya que es demasiado primitivo para comprender el propósito de este patrón). Su rutina "principal" en la estrategia requiere algunos métodos abstractos. Por ejemplo, "Enter Room Strategy", "main-method" es goThroughDoor (), que se ve así: enfoqueDoor (), if (bloqueado ()) openLock (); puerta abierta(); enterRoom (); giro(); closeDoor (); if (wasLocked ()) lockDoor ();

Ahora las subclases de este "algoritmo" general para moverse de una habitación a otra a través de una posible puerta cerrada pueden implementar los pasos del algoritmo.

En otras palabras, la subclasificación de la estrategia no cambia los algoritmos básicos, solo los pasos individuales.

QUE ARRIBA es un patrón de método de plantilla. Ahora coloque los pasos que pertenecen juntos (desbloqueo / bloqueo y apertura / cierre) en sus propios objetos de implementación y delegue en ellos. Por ejemplo, una cerradura con una llave y una cerradura con una tarjeta de código son dos tipos de cerraduras. Delegue de la estrategia a los objetos "Paso". Ahora tienes un patrón de estrategia.

Un patrón de estado es algo completamente diferente.

Tiene un objeto de envoltura y el objeto envuelto. El envuelto es el "estado". Solo se accede al objeto de estado a través de su contenedor. Ahora puede cambiar el objeto envuelto en cualquier momento, por lo que el contenedor parece cambiar su estado, o incluso su "clase" o tipo.

Por ejemplo, tiene un servicio de inicio de sesión. Acepta un nombre de usuario y una contraseña. Solo tiene un método: inicio de sesión (String userName, String passwdHash). En lugar de decidir por sí mismo si se acepta o no un inicio de sesión, delega la decisión a un objeto de estado. Ese objeto de estado generalmente solo verifica si la combinación usuario / pase es válida y realiza un inicio de sesión. Pero ahora puede intercambiar el "Comprobador" por uno que solo permita que los usuarios privilegiados inicien sesión (durante el tiempo de mantenimiento, por ejemplo) o por uno que no permita que nadie inicie sesión. Eso significa que el "verificador" expresa el "estado de inicio de sesión" del sistema.

La diferencia más importante es: cuando has elegido una estrategia, la mantienes hasta que hayas terminado. Eso significa que usted llama a su "método principal" y mientras ese se esté ejecutando, nunca cambiará la estrategia. OTOH en una situación de patrón de estado durante el tiempo de ejecución de su sistema, cambia el estado arbitrariamente como mejor le parezca.

Angel O'Sphere
fuente
9

El patrón de estrategia se utiliza cuando tiene un algoritmo múltiple para una tarea específica y el cliente decide la implementación real que se utilizará en tiempo de ejecución.

Diagrama UML del artículo del patrón de estrategia wiki :

ingrese la descripción de la imagen aquí

Características clave:

  1. Es un patrón de comportamiento.
  2. Se basa en la delegación.
  3. Cambia las tripas del objeto modificando el comportamiento del método.
  4. Se usa para cambiar entre la familia de algoritmos.
  5. Cambia el comportamiento del objeto en tiempo de ejecución.

Consulte esta publicación para obtener más información y ejemplos del mundo real:

Ejemplo del mundo real del patrón de estrategia

El patrón de estado permite que un objeto altere su comportamiento cuando cambia su estado interno

Diagrama UML del artículo del patrón wiki State:

ingrese la descripción de la imagen aquí

Si tenemos que cambiar el comportamiento de un objeto en función de su estado, podemos tener una variable de estado en el Objeto y usar el bloque de condiciones if-else para realizar diferentes acciones en función del estado. El patrón de estado se utiliza para proporcionar una forma sistemática y acoplada por pérdida para lograr esto a través de implementaciones de contexto y estado .

Consulte este artículo de journaldev para obtener más detalles.

Diferencias clave con respecto a la creación de fuentes y artículos de journaldev :

  1. La diferencia entre Estado y Estrategia radica en el tiempo vinculante. La estrategia es un patrón de vinculación única, mientras que el estado es más dinámico .
  2. La diferencia entre Estado y Estrategia está en la intención. Con Strategy, la elección del algoritmo es bastante estable . Con Estado, un cambio en el estado del objeto "contexto" hace que seleccione de su "paleta" de objetos Estrategia .
  3. El contexto contiene el estado como variable de instancia y puede haber múltiples tareas cuya implementación puede depender del estado, mientras que en la estrategia el patrón de estrategia se pasa como argumento al método y el objeto de contexto no tiene ninguna variable para almacenarlo.
Ravindra babu
fuente
5

En lenguaje laico,

en el patrón de Estrategia, no hay estados o todos tienen el mismo estado. Todo lo que uno tiene son diferentes formas de realizar una tarea, como diferentes médicos tratan la misma enfermedad del mismo paciente con el mismo estado de diferentes maneras.

En el patrón de estado, subjetivamente hay estados, como el estado actual del paciente (por ejemplo, temperatura alta o temperatura baja), en función del siguiente curso de acción (prescripción de medicamentos) y un estado puede conducir a otro estado, por lo que hay un estado para declarar dependencia (composición técnicamente).

Si técnicamente tratamos de entenderlo, basándonos en la comparación de código de ambos, podríamos perder la subjetividad de la situación, porque ambos parecen muy similares.

pkgrocz
fuente
2

Ambos patrones delegan a una clase base que tiene varias derivadas, pero es solo en el patrón de estado que estas clases derivadas retienen una referencia a la clase de contexto.

Otra forma de verlo es que el patrón de Estrategia es una versión más simple del patrón de Estado; un subpatrón, si quieres. Realmente depende de si desea que los estados derivados retengan referencias al contexto o no (es decir, si desea que invoquen métodos en el contexto).

Para más información: Robert C Martin (y Micah Martin) responden esto en su libro, "Principios, patrones y prácticas ágiles en C #". ( Http://www.amazon.com/Agile-Principles-Patterns-Practices-C/dp/0131857258 )

Adrian K
fuente
2

Esta es una pregunta bastante antigua, pero aun así, también estaba buscando las mismas respuestas y esto es lo que he descubierto.

Para el patrón de estado, consideremos un ejemplo del botón Reproducir jugador intermedio. Cuando jugamos, comienza a jugar y hace que el contexto sea consciente de que está jugando. Cada vez que el cliente desea realizar una operación de juego, verifica el estado actual del jugador. Ahora el cliente sabe que el estado del objeto se está reproduciendo a través del objeto de contexto, por lo que llama al método de acciones de objetos de estado de pausa. La parte del cliente que se da cuenta del estado y en qué estado necesita actuar puede automatizarse.

https://www.youtube.com/watch?v=e45RMc76884 https://www.tutorialspoint.com/design_pattern/state_pattern.htm

En el caso del patrón de estrategia, la disposición del diagrama de clase es la misma que la del patrón de estado. El cliente llega a este acuerdo para hacer alguna operación. Es decir, en lugar de los diferentes estados, hay diferentes algoritmos, por ejemplo, diferentes análisis que deben realizarse en el patrón. Aquí los clientes le dicen al contexto qué quiere hacer, qué algoritmo (algoritmo personalizado definido por el negocio) y luego lo realizan.

https://www.tutorialspoint.com/design_pattern/strategy_pattern.htm

Ambos implementan el principio de cierre abierto para que el desarrollador tenga la capacidad de agregar nuevos estados al patrón de estado y al nuevo algoritmo.

Pero la diferencia es lo que se usan, es decir, el patrón de estado utilizado para ejecutar diferentes lógicas basadas en un estado del objeto. Y en un caso de estrategia lógica diferente.

Ameya
fuente
2

El estado viene con dependencias un poco dentro de las clases derivadas del estado: como un estado sabe sobre otros estados que vienen después de él. Por ejemplo, el verano llega después del invierno para cualquier estado de temporada, o el estado de entrega después del estado de depósito para compras.

Por otro lado, la estrategia no tiene dependencias como estas. Aquí, cualquier tipo de estado se puede inicializar en función del tipo de programa / producto.

MH Rahman
fuente
1

La diferencia se discute en http://c2.com/cgi/wiki?StrategyPattern . He utilizado el patrón de estrategia para permitir que se elijan diferentes algoritmos dentro de un marco general para analizar datos. A través de eso, puede agregar algoritmos sin tener que cambiar los marcos generales y su lógica.

Un ejemplo típico es que puede tener un marco para optimizar una función. El marco establece los datos y parámetros. El patrón de estrategia le permite seleccionar algoritmos tales como descensos más fuertes, gradientes conjugados, BFGS, etc. sin alterar el marco.

peter.murray.rust
fuente
1

Tanto la estrategia como el patrón estatal tienen la misma estructura. Si observa el diagrama de clase UML para ambos patrones, se ven exactamente iguales, pero su intención es totalmente diferente. El patrón de diseño de estado se usa para definir y administrar el estado de un objeto, mientras que el patrón de estrategia se usa para definir un conjunto de algoritmos intercambiables y permite al cliente elegir uno de ellos. Por lo tanto, el patrón de estrategia es un patrón impulsado por el cliente, mientras que Object puede administrar su propio estado.

Rakesh KR
fuente
1

En resumen, con el patrón de estrategia podemos establecer un comportamiento sobre la marcha, con el patrón de estado, podemos estar seguros de que un objeto cambiará su comportamiento internamente con el cambio de su estado.

rastaman
fuente
0

Cuando tienes un proyecto que se puede dividir en 2 tareas:

tarea 1: puede usar uno de dos algoritmos diferentes para lograr: alg1, alg2

tarea 2: puede usar uno de los tres algoritmos diferentes para lograr: alg3, alg4, alg5

alg1 y alg2 son intercambiables; alg3, alg4 y alg5 son intercambiables.

Elegir qué algoritmo realizar en la tarea 1 y la tarea 2 depende de los estados:

estado 1: necesita alg1 en la tarea 1 y alg3 en la tarea 2

estado 2: necesita alg2 en la tarea 1 y alg5 en la tarea 2

Su contexto puede cambiar el objeto de estado del estado 1 al estado 2. Luego, su tarea sería realizada por alg2 y alg5, en lugar de alg1 y alg3.

Puede agregar más algoritmos intercambiables para la tarea 1 o la tarea 2. Este es el patrón de estrategia.

Puede tener más estados con diferentes combinaciones de algoritmos en la tarea 1 y la tarea 2. El patrón de estado le permite cambiar de un estado a otro y realizar diferentes combinaciones de algoritmos.

usuario791961
fuente
0

'Estrategia' es solo un algoritmo que puede cambiarlo en diferentes circunstancias según su necesidad, y procesa algo por usted. Ex. Puedes elegir cómo comprimir un archivo. zip o rar ... en un método.

Pero 'Estado' PUEDE cambiar todo el comportamiento de su objeto, cuando cambia, incluso puede cambiar otros campos ... es por eso que tiene una referencia a su propietario. Debería notar que cambiar un campo de objeto puede cambiar el comportamiento del objeto. Ex. cuando cambia State0 a State1 en obj, cambia un número entero a 10 .. así que cuando llamamos a obj.f0 () que hace algunos cálculos y usa ese número entero, afecta el resultado.

Ali Dahaghin
fuente