design-patterns - patron - strategy pattern
¿Cuál es la diferencia entre el patrón de diseño de estrategia y el patrón de diseño de estado? (16)
¿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 revisando bastantes artículos en la web pero no pude ver la diferencia claramente.
¿Alguien puede explicar la diferencia en los términos del laico?
¿Alguien puede explicar en términos sencillos?
Los patrones de diseño no son realmente conceptos "legos", pero trataré de hacerlo lo más claro posible. Cualquier patrón de diseño se puede considerar en tres dimensiones:
- El problema que resuelve el patrón;
- La estructura estática del patrón (diagrama de clases);
- La dinámica del patrón (diagramas de secuencia).
Vamos a comparar Estado y Estrategia.
Problema que resuelve el patrón
El estado se usa en uno de dos casos [libro GoF 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 de varias partes 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 pone 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 quiere asegurarse de que realmente tiene el problema que resuelve el patrón de estado, debería poder modelar los estados del objeto usando una máquina de estados finitos . Puede encontrar un ejemplo aplicado here .
Cada transición de estado es un método en la interfaz de estado. Esto implica que para un diseño, debe estar seguro 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 lo implementan.
Personalmente, no he encontrado este patrón tan útil. Siempre puede implementar máquinas de estados finitos usando una tabla de búsqueda (no es una forma OO, pero funciona bastante bien).
La estrategia se utiliza para lo siguiente [Libro GoF p. 316] :
- muchas clases relacionadas difieren solo en su comportamiento. Las estrategias proporcionan una forma de configurar una clase con uno de muchos comportamientos.
- necesitas diferentes variantes de un algoritmo. Por ejemplo, puede definir algoritmos que reflejen diferentes intercambios de espacio / tiempo. Las estrategias se pueden usar cuando estas variantes se implementan como una jerarquía de clases de algoritmos [HO87].
- un algoritmo utiliza datos que los clientes no deberían conocer. Utilice el patrón de estrategia para evitar exponer estructuras de datos complejas y específicas de algoritmo.
- una clase define muchos comportamientos, y estos aparecen como múltiples declaraciones condicionales en sus operaciones. En lugar de muchos condicionales, mueva las 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 condicionalmente por polimorfismo .
Resumen: Estado y Estrategia resuelven problemas muy diferentes. Si su problema no puede ser modelado con una máquina de estado finito, entonces el patrón de estado probable no es apropiado. Si su problema no es encapsular las variantes de un algoritmo complejo, entonces la Estrategia no se aplica.
Estructura estática del patrón
El estado tiene la siguiente estructura de clase UML:
La estrategia tiene la siguiente estructura de clase UML:
Resumen: en términos de la 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, lo que impide su distinción mediante un proceso automático (por ejemplo, sin referirse a información conceptual) " .
Sin embargo, puede haber una gran diferencia 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 (ver la siguiente sección), el estado A determina la transición al estado B. Si la clase Contexto decide la transición al siguiente estado concreto, estas dependencias desaparecerán.
Dinámica del patrón
Como se menciona en la sección de Problemas anterior, el estado implica que el comportamiento cambia en tiempo de ejecución según el 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 se pueden definir en las subclases ConcreteState o en una ubicación centralizada (como una ubicación basada en tablas).
Supongamos una máquina de estado finito simple:
Suponiendo que las subclases deciden la transición de estado (devolviendo el siguiente objeto de estado), la dinámica se ve más o menos así:
Para mostrar la dinámica de la Estrategia , es útil tomar prestado un ejemplo real .
Resumen : cada patrón usa una llamada polimórfica para hacer algo dependiendo del 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 generalmente no cambia el contexto (por ejemplo, pagar con tarjeta de crédito una vez no implica que pagará con PayPal la próxima vez). De nuevo, la dinámica del patrón de estado está determinada por su correspondiente máquina de estado fininte, que (para mí) es esencial para la correcta aplicación de este patrón.
Ambos patrones delegan en una clase base que tiene varias derivadas, pero solo en el patrón de Estado estas clases derivadas mantienen una referencia de regreso 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 si desea que los estados derivados tengan 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 ágiles, patrones y prácticas en C #". ( http://www.amazon.com/Agile-Principles-Patterns-Practices-C/dp/0131857258 )
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
- Vacaciones
Para manejar esta situación, puede usar un patrón de estado .
- Holiday : IVR simplemente responde diciendo que ''las llamadas se pueden realizar solo en días hábiles entre las 9am y las 5pm ''.
- Días de trabajo : responde al conectar al cliente con un ejecutivo de atención al cliente.
Este proceso de conectar un cliente con un ejecutivo de soporte puede implementarse usando un Patrón de estrategia donde los ejecutivos son seleccionados en base a cualquiera de:
- Round Robin
- Menos usado recientemente
- Otros algoritmos basados en prioridad
El patrón de estrategia decide sobre " cómo " realizar alguna acción y el patrón de estado decide cuándo ejecutarlas.
El estado viene con un poco de dependencias dentro de las clases derivadas del estado: como un estado sabe acerca de otros estados que lo siguen. Por ejemplo, el verano viene después del invierno para cualquier estado de temporada, o el estado de entrega después del estado de depósito para ir de compras.
Por otro lado, Strategy no tiene dependencias como estas. Aquí, cualquier tipo de estado se puede inicializar según el tipo de programa / producto.
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 en función del estado, al tiempo que se deja a la persona que llama aliviada de la carga de acomodar todos los estados posibles. Entonces, por ejemplo, podría tener un método getStatus()
que devolverá diferentes estados en función del estado del objeto, pero no es necesario codificar de forma diferente al llamador del método para tener en cuenta cada estado potencial.
El patrón de estrategia implica mover la implementación de un algoritmo de una clase de alojamiento y ponerlo en una clase separada. Esto significa que la clase de host no necesita proporcionar la implementación de cada algoritmo en sí, lo que probablemente conduzca a un código sucio.
Los algoritmos de clasificación se usan generalmente como ejemplo, ya que todos hacen el mismo tipo de cosas (clasificación). Si cada algoritmo de clasificación diferente se coloca en su propia clase, entonces 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 el estado del objeto cambia. Esto significa que la clase de host no ha proporcionado 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 determinado y cambia a una clase diferente cuando el estado cambia
En lenguaje sencillo,
en el patrón de Estrategia, no hay estados o todos ellos tienen el mismo estado. Todo lo que uno tiene es maneras diferentes de realizar una tarea, como diferentes doctores tratan la misma enfermedad del mismo paciente con el mismo estado de diferentes maneras.
En Patrón de estado, subjetivamente hay estados, como el estado actual del paciente (por ejemplo, alta temperatura o baja temperatura), en función del siguiente curso de acción (prescripción de medicamentos) se decidirá. Y un estado puede conducir a otro estado, por lo que hay un estado a la dependencia del estado (composición técnicamente).
Si técnicamente tratamos de entenderlo, basándonos en la comparación del código de ambos, podríamos perder la subjetividad de la situación, porque ambos se ven muy similares.
En resumen, con el patrón de estrategia podemos establecer algún comportamiento sobre la marcha, con un patrón de estado, podemos estar seguros, de que un objeto cambiará su comportamiento internamente con el cambio de su estado.
Esta es una pregunta muy antigua, pero aún así, también estaba buscando las mismas respuestas y esto es lo que he descubierto.
Para el patrón de estado, consideremos un ejemplo de botón Reproducir de reproductor medial. Cuando jugamos, comienza a jugar y hace que el contexto sepa que está sonando. Cada vez que el cliente desea realizar una operación de juego, él 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 debe actuar se puede automatizar.
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 el 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 que dicen, por ejemplo, diferentes análisis que deben realizarse en el patrón. Aquí los clientes le dicen al contexto qué es lo que quiere hacer, qué algoritmo (algoritmo personalizado definido por el negocio) y luego lo realiza.
https://www.tutorialspoint.com/design_pattern/strategy_pattern.htm
Ambos implementos abren el principio de cierre 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 utilizan, que es el patrón de estado utilizado para ejecutar lógica diferente en función de un estado del objeto. Y en un caso de estrategia diferente lógica.
Estrategia: la estrategia es fija y generalmente consta de varios pasos. (La ordenación constituye solo un paso y, por lo tanto, es un muy mal ejemplo, ya que es demasiado primitivo para comprender el propósito de este patrón). Su rutina "principal" en la estrategia es llamar a algunos métodos abstractos. Por ejemplo, "Enter Room Strategy", "main-method" es goThroughDoor (), que se ve así: approachDoor (), if (locked ()) openLock (); puerta abierta(); enterRoom (); giro(); closeDoor (); if (wasLocked ()) lockDoor ();
Ahora las subclases de este "algoritmo" general para pasar 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 ponga los pasos que pertenecen juntos (desbloqueo / bloqueo y apertura / cierre) en sus propios objetos de implementación y delegue en ellos. Por ejemplo, un candado con una llave y un candado con una tarjeta de códigos son dos tipos de candados. Delegue de la estrategia a los objetos "Paso". Ahora tienes un patrón de Estrategia.
Un patrón de estado es algo completamente diferente.
Usted tiene un objeto de envoltura y el objeto envuelto. El envuelto es el "estado". El objeto de estado solo se puede acceder a través de su envoltorio. 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 de usuario / pase es válida y realiza un inicio de sesión. Pero ahora puede intercambiar el "Verificador" por uno que solo permita el inicio de sesión de usuarios privilegiados (durante el tiempo de mantenimiento, por ejemplo) o por uno que no permita el inicio de sesión. Eso significa que el "verificador" expresa el "estado de inicio de sesión" del sistema.
La diferencia más importante es: cuando ha elegido una estrategia, la sigue hasta que haya terminado con ella. Eso significa que usted llama su "método principal" y mientras eso se esté ejecutando, nunca cambia la estrategia. OTOH en una situación de patrón de estado durante el tiempo de ejecución de su sistema, cambia de estado arbitrariamente según lo crea conveniente.
Honestamente, los dos patrones son bastante similares en la práctica, y la diferencia de definición entre ellos tiende a variar dependiendo de a quién le preguntes. Algunas elecciones populares son:
- Los estados almacenan una referencia al objeto de contexto que los contiene. Las estrategias no.
- Los estados pueden reemplazarse (IE: para cambiar el estado del objeto de contexto a otra cosa), mientras que las estrategias no lo son.
- Las estrategias se pasan al objeto de contexto como parámetros, mientras que los Estados se crean mediante el objeto de contexto mismo.
- Las estrategias solo manejan una única tarea específica, mientras que los estados proporcionan la implementación subyacente para todo (o la mayoría de las cosas) 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 encontrará con híbridos que tienen mezclas de ambos. Si una determinada es más State-y o Strategy-y es, en última instancia, una pregunta subjetiva.
La diferencia radica simplemente 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 de Estrategia trata de cómo un objeto realiza una determinada tarea: encapsula un algoritmo.
Los constructos para alcanzar estos objetivos diferentes son sin embargo muy similares; ambos patrones son ejemplos de composición con delegación.
Algunas observaciones sobre sus ventajas:
Al usar el patrón de Estado , la clase de mantenimiento de estado (contexto) se alivia del conocimiento de qué estado o tipo es y qué estados o tipos 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 qué estados / tipos hay, pero los estados / tipos están abiertos a extensiones.
Al usar el patrón de Estrategia , la clase de uso de algoritmo (contexto) se alivia 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á abierto a adiciones 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 se vuelve fácilmente disponible para su reutilización por otras clases.
La diferencia se analiza 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 tienes un marco para optimizar una función. El marco establece los datos y parámetros. El patrón de estrategia le permite seleccionar algoritmos, como descensos en pendiente, degradados conjugados, BFGS, etc., sin alterar el marco.
La estrategia representa objetos que "hacen" algo, con los mismos resultados de inicio y finalización, pero internamente utilizando diferentes metodologías. En ese sentido, son análogos a la representación de 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 pueden representar operaciones sobre esos datos también, son más análogos a la representación de un sustantivo que de un verbo, y se adaptan a las máquinas de estado.
Tanto el patrón de Estrategia como el de Estado tienen la misma estructura. Si miras el diagrama de clases UML para ambos patrones, se ven exactamente iguales, pero su intención es totalmente diferente. El patrón de diseño del 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. Entonces, el patrón de estrategia es un patrón manejado por el cliente mientras que Object puede administrarlo allí mismo.
El patrón de estrategia se usa cuando tiene múltiples algoritmos para una tarea específica y el cliente decide la implementación real que se utilizará en el tiempo de ejecución.
Diagrama UML de wiki Artículo de patrón de estrategia:
Principales características:
- Es un patrón de comportamiento.
- Está basado en la delegación.
- Cambia las agallas del objeto modificando el comportamiento del método.
- Se usa para cambiar entre familia de algoritmos.
- 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 modifique su comportamiento cuando cambia su estado interno
Diagrama UML del artículo de patrón de estado de wiki :
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 condición if-else para realizar diferentes acciones basadas en el estado. El patrón de estado se utiliza para proporcionar una forma sistemática y de pérdida de acoplamiento para lograr esto a través de implementaciones de contexto y estado .
Consulte este artículo de journaldev para más detalles.
Diferencias clave de los artículos sourcemaking y journaldev :
- La diferencia entre Estado y Estrategia radica en el tiempo de vinculación. La estrategia es un patrón de vincular una vez, mientras que el estado es más dinámico .
- La diferencia entre Estado y Estrategia está en la intención. Con Strategy, la elección del algoritmo es bastante estable . Con State, un cambio en el estado del objeto "context" hace que seleccione de su "paleta" de objetos Strategy .
- El contexto contiene estado como variable de instancia y puede haber múltiples tareas cuya implementación puede depender del estado, mientras que en estrategia la estrategia de patrón se pasa como argumento para el método y el objeto de contexto no tiene ninguna variable para almacenarlo.