Strategy Pattern: Algoritmos Intercambiables
Aprende a definir una familia de algoritmos intercambiables usando el patrón Strategy, permitiendo que el comportamiento de un objeto cambie en tiempo de ejecución sin modificar su estructura.
TL;DR - Resumen rápido
- El Strategy Pattern define una familia de algoritmos intercambiables
- Cada estrategia encapsula un algoritmo específico en una clase separada
- El contexto delega la ejecución a la estrategia actual
- Permite cambiar el comportamiento en tiempo de ejecución
- Elimina condicionales complejos switch/case o if/else
Introducción al Strategy Pattern
El Strategy Pattern es un patrón de diseño comportamental que te permite definir una familia de algoritmos, encapsular cada uno en una clase separada, y hacerlos intercambiables. Este patrón es especialmente útil cuando tienes múltiples formas de resolver un problema y necesitas cambiar entre ellas en tiempo de ejecución.
En JavaScript, el patrón Strategy es ideal para eliminar condicionales complejos como switch/case o largas cadenas de if/else. En lugar de tener un método con múltiples ramas condicionales, creas estrategias separadas para cada caso y delegas la ejecución a la estrategia apropiada.
Strategy vs Factory Pattern
El Strategy Pattern define cómo se ejecutan algoritmos intercambiables, mientras que el Factory Pattern define cómo se crean objetos. A menudo se usan juntos: el Factory crea la estrategia apropiada, y el Contexto usa esa estrategia para ejecutar el algoritmo.
Concepto del Strategy Pattern
El patrón Strategy consta de tres componentes principales: la interfaz Strategy (que define el método execute), las Concrete Strategies (que implementan diferentes algoritmos), y el Context (que usa la estrategia para resolver un problema). El contexto mantiene una referencia a la estrategia actual y delega la ejecución a ella.
Implementación Básica
Una implementación básica del Strategy Pattern requiere definir una interfaz común para todas las estrategias y crear implementaciones concretas para cada algoritmo. El contexto usa la estrategia sin conocer los detalles de implementación.
Este ejemplo muestra cómo implementar el patrón Strategy para diferentes algoritmos de ordenamiento. Cada estrategia encapsula un algoritmo diferente, y el contexto puede cambiar entre estrategias en tiempo de ejecución sin modificar su código.
Eliminación de Condicionales
El Strategy Pattern es especialmente útil para eliminar condicionales complejos. En lugar de un switch/case con múltiples casos, tienes una estrategia para cada caso. Esto hace el código más limpio, más fácil de mantener, y facilita agregar nuevos algoritmos sin modificar el código existente.
Cambio Dinámico de Estrategias
Una de las ventajas más poderosas del patrón Strategy es que puedes cambiar la estrategia en tiempo de ejecución. Esto permite que el comportamiento del contexto se adapte dinámicamente según las condiciones del entorno o las preferencias del usuario.
Este ejemplo demuestra cómo cambiar la estrategia de cálculo de precios dinámicamente según el tipo de cliente. El contexto puede cambiar entre estrategias sin modificar su lógica interna, lo que hace el código más flexible y mantenible.
- Cada estrategia encapsula un algoritmo específico
- Las estrategias implementan la misma interfaz
- El contexto delega la ejecución a la estrategia actual
- Las estrategias pueden cambiarse en tiempo de ejecución
- Este patrón elimina condicionales complejos switch/case
Ventajas del Strategy Pattern
El Strategy Pattern ofrece ventajas significativas cuando necesitas cambiar algoritmos dinámicamente o tienes múltiples formas de resolver un problema. Es especialmente valioso en escenarios donde los condicionales complejos hacen el código difícil de mantener.
- Elimina condicionales complejos switch/case o if/else largos
- Permite cambiar algoritmos en tiempo de ejecución según necesidades
- Facilita agregar nuevas estrategias sin modificar el código existente
- Promueve el principio Open/Closed (abierto para extensión, cerrado para modificación)
- Cada estrategia es independiente y puede probarse por separado
- El código es más limpio y fácil de entender al separar algoritmos
Simplificación de Código Condicional
El Strategy Pattern es especialmente poderoso para eliminar condicionales complejos. En lugar de un switch/case con 10 casos diferentes, tienes 10 estrategias separadas. Esto hace el código más mantenible y facilita agregar nuevos casos sin tocar código existente.
El patrón Strategy se combina perfectamente con otros patrones como Factory (para crear la estrategia apropiada) y Dependency Injection (para inyectar estrategias en el contexto). Esta combinación crea arquitecturas altamente flexibles y mantenibles.
Casos de Uso Reales
El Strategy Pattern tiene numerosas aplicaciones en desarrollo web moderno. Desde validación de formularios hasta procesamiento de pagos y compresión de datos, este patrón es ideal para cualquier escenario donde tengas múltiples formas de resolver un problema.
Este ejemplo muestra cómo usar el patrón Strategy para implementar diferentes métodos de validación de formularios. Cada estrategia encapsula la lógica de validación para un tipo de campo específico, y el formulario puede cambiar entre estrategias según el tipo de campo.
Errores Comunes
Al implementar el patrón Strategy, existen varios errores comunes que pueden causar comportamientos inesperados, bugs difíciles de depurar, o código difícil de mantener. Es importante conocer estos patrones de error para evitarlos.
Interfaz Inconsistente entre Estrategias
El error más común es crear estrategias que no implementan la misma interfaz. Esto rompe el polimorfismo y hace imposible que el contexto use las estrategias de forma intercambiable.
El primer error en el ejemplo muestra cómo una estrategia con un método diferente (execute vs process) causa un error en tiempo de ejecución. La solución es definir una clase base con la interfaz esperada y hacer que todas las estrategias la extiendan.
Advertencia: Interfaz Consistente
Siempre define una clase base o interfaz para tus estrategias. Todas las estrategias deben implementar exactamente los mismos métodos con las mismas firmas. Esto garantiza que sean intercambiables sin romper el código del contexto.
Mutar Estado Compartido del Contexto
Las estrategias no deberían modificar el estado del contexto directamente. Esto crea acoplamiento y efectos secundarios inesperados que hacen el código difícil de predecir y depurar.
El segundo error muestra cómo una estrategia que modifica el estado del contexto rompe el principio de inmutabilidad. Las estrategias deben ser funciones puras que reciben datos y devuelven resultados sin modificar el estado compartido.
No Actualizar la Estrategia cuando Cambia el Contexto
Olvidar actualizar la estrategia cuando cambian las condiciones del contexto es un error sutil pero común. Si el tipo de cliente cambia a "premium" pero sigues usando la estrategia "regular", obtienes resultados incorrectos.
El tercer error demuestra cómo olvidar actualizar la estrategia causa que se use el algoritmo incorrecto. La solución es mantener un mapa de estrategias y seleccionar la apropiada automáticamente según el estado del contexto.
Resumen: Strategy Pattern
Conceptos principales:
- •El Strategy Pattern define una familia de algoritmos intercambiables
- •Cada estrategia encapsula un algoritmo en una clase separada
- •El contexto delega la ejecución a la estrategia actual
- •Las estrategias pueden cambiarse en tiempo de ejecución
- •Elimina condicionales complejos switch/case o if/else
Mejores prácticas:
- •Usa estrategias para algoritmos que cambian frecuentemente
- •Asegúrate de que todas las estrategias implementen la misma interfaz
- •Documenta claramente qué hace cada estrategia
- •Considera usar un Factory Pattern para crear estrategias
- •Evita que las estrategias dependan del estado del contexto