Sé que esta es una pregunta antigua, pero creo que tengo otro ejemplo interesante que implementé recientemente.
Este es un ejemplo muy práctico del patrón de estrategia que se utiliza en un sistema de entrega de documentos.
Tenía un sistema de entrega de PDF que recibía un archivo que contenía muchos documentos y algunos metadatos. Basándose en los metadatos, decidió dónde colocar el documento; por ejemplo, en función de los datos, podría almacenar el documento en A
, B
o C
sistemas de almacenamiento, o una mezcla de los tres.
Diferentes clientes usaban este sistema y tenían diferentes requisitos de gestión de reversión / error en caso de errores: uno quería que el sistema de entrega se detuviera ante el primer error, dejara todos los documentos ya entregados en sus almacenes, pero detuviera el proceso y no entregara nada más. ; otro quería que se revertiera B
en caso de errores al almacenar C
, pero dejar lo que ya se envió A
. Es fácil imaginar que un tercero o cuarto también tendrá diferentes necesidades.
Para resolver el problema, he creado una clase de entrega básica que contiene la lógica de entrega, además de métodos para revertir cosas de todos los almacenamientos. En realidad, el sistema de entrega no llama a esos métodos directamente en caso de errores. En su lugar, la clase usa Inyección de dependencia para recibir una clase de "Estrategia de reversión / manejo de errores" (basada en el cliente que usa el sistema), que se llama en caso de errores, que a su vez llama a los métodos de reversión si es apropiado para esa estrategia.
La clase de entrega en sí informa lo que está sucediendo a la clase de estrategia (qué documentos se entregaron a qué almacenamientos y qué fallas sucedieron), y siempre que ocurre un error, pregunta a la estrategia si continuar o no. Si la estrategia dice "deténgalo", la clase llama al método "cleanUp" de la estrategia, que usa la información reportada previamente para decidir qué métodos de reversión llamar desde la clase de entrega, o simplemente no hacer nada.
rollbackStrategy.reportSuccessA(...);
rollbackStrategy.reportFailureB(...);
if (rollbackStrategy.mustAbort()) {
rollbackStrategy.rollback(); // rollback whatever is needed based on reports
return false;
}
Así que ahora tengo dos estrategias diferentes: una es la QuitterStrategy
(que se cierra con el primer error y no limpia nada) y la otra es la MaximizeDeliveryToAStrategy
(que intenta en la medida de lo posible no abortar el proceso y nunca revertir las cosas entregadas al almacenamiento A
, pero deshace cosas de B
si la entrega C
falla).
Según tengo entendido, este es un ejemplo del patrón de estrategia. Si usted (sí, está leyendo) cree que estoy equivocado, por favor comente a continuación y hágamelo saber. Tengo curiosidad por saber qué constituiría un uso "puro" del patrón de estrategia y qué aspectos de mi implementación violan la definición. Creo que se ve un poco divertido porque la interfaz de estrategia es un poco gruesa. Todos los ejemplos que he visto hasta ahora utilizan un solo método, pero sigo pensando que encapsula un algoritmo (si una parte de la lógica empresarial puede considerarse un algoritmo, lo cual creo que sí).
Dado que la estrategia también recibe notificaciones sobre eventos durante la ejecución de la entrega, también se puede considerar un observador , pero esa es otra historia.
Al hacer una pequeña investigación, parece que se trata de un "patrón compuesto" (como MVC, un patrón que utiliza múltiples patrones de diseño debajo de una manera particular) llamado Asesor . Es un asesor sobre si la entrega debe continuar o no, pero también es un manejador de errores activo, ya que puede revertir cosas cuando se le solicite.
De todos modos, este es un ejemplo bastante complejo que puede hacer que sienta que los usos del patrón de estrategia son demasiado simples / tontos. Puede ser realmente complejo e incluso más aplicable cuando se usa junto con otros patrones.