Imagina que eres el director técnico de un equipo de fútbol, y tienes un juego muy importante el próximo domingo, ¿cómo plantearías el juego?.
Como eres un buen director técnico, tienes que prever los posibles escenarios y tener una estrategia preparada para cada contexto.
De esa manera la formación y/o comportamiento de tus jugadores deberían cambiar dependiendo de los diversos factores que se presenten en el desarrollo juego, tales como: cuando atacas, cuando defiendes, expulsan a un jugador, vas ganando, vas perdiendo, juegan de visita, juegan de local, el rival es débil, el rival es fuerte, etc.
Nuestra planificación sería de esta manera:
Con esto en mente veamos la parte técnica.
Definición
Este patrón define un conjunto de algoritmos, encapsula cada uno de ellos y los hace intercambiables. Permite que el algoritmo pueda variar independientemente de los clientes que lo utilicen.
Esto quiere decir que nuestros objetos deben estar preparados para afrontar diversos contextos sin cambiar las interacciones de estos con el cliente.
Recuerda: Un algoritmo encapsulado es una estrategia
Modelo UML
Participantes:
Las clases y objetos que participan en este modelo son:
- Strategy
- Declara una interfaz común para todos los algoritmos compatibles. El Contex utiliza esta interfaz para llamar al algoritmo definido por un ConcreteStrategy
- ConcreteStrategy
- Implementa el algoritmo utilizando la interfaz de Strategy
- Context
- Está configurado con un objeto ConcreteStrategy
- Mantiene una referencia a un objeto de Strategy
- Puede definir una interfaz que le permite acceder a sus datos Strategy.
Strategy Pattern en Acción
Notas
El patrón Strategy (estrategia) es una alternativa a la herencia, si estás pensando usar la herencia para poder agregar nuevos comportamientos a tus objetos, sería conveniente usar este patrón
Si dentro de tu clase haces uso intensivo de las condicionales if
, else
, swicth
, case, eso quiere decir que tu clase tiene asignado muchos comportamientos y/o responsabilidades, lo cual suele ser un indicador de la necesidad aplicar el patrón Strategy (estrategia), para poder encapsular estos comportamientos y delegarlos a otra clase u objeto.
Veamos como se traduce la definición de este patrón a un código PHP
Context
Definimos nuestra clase Context
, donde se pasarán las estrategias
namespace Behavioral\Strategy\Difinition; class Context { private $strategy; public function __construct($strategy) { $this->strategy = $strategy; } public function contextInterface() { $this->algorithmInterface(); } }
Strategy
Defendimos una interface StratageyInterface
del cual se implementaran las demás estrategias
// StratageyInterface.php namespace Behavioral\Strategy\Difinition; interface StratageyInterface { public function algorithmInterface(); }
ConcreteStrategy
Definimos una estrategia concreta llamada ConcreteStrategyA
que encapsula nuestro algoritmo de comportamiento
//ConcreteStrategyA namespace Behavioral\Strategy\Difinition; use Behavioral\Strategy\Difinition\StratageyInterface; class ConcreteStrategyA implements StratageyInterface { public function algorithmInterface() { echo "Called ConcreteStrategyA->algorithmInterface()"; } }
Definimos otra estrategia concreta llamada ConcreteStrategyB
que encapsula otro algoritmo de comportamiento
namespace Behavioral\Strategy\Difinition; use Behavioral\Strategy\Difinition\StratageyInterface; class ConcreteStrategyB implements StratageyInterface { public function algorithmInterface() { echo "Called ConcreteStrategyB->algorithmInterface()"; } }
Main
Este seria la manera como invocaríamos a nuestro código
use Behavioral\Strategy\Difinition\Context; use Behavioral\Strategy\Difinition\ConcreteStrategyA; use Behavioral\Strategy\Difinition\ConcreteStrategyB; $contextA = new Context(new ConcreteStrategyA()); $contextA->contextInterface(); //Show //Called ConcreteStrategyA->algorithmInterface() $contextB = new Context(new ConcreteStrategyB()); $contextB->contextInterface(); //Show //Called ConcreteStrategyB->algorithmInterface()
Ejemplos del Mundo Real
Veamos la implementación de de una pequeña tienda virtual
Strategy Patern en acción con PHP
Conclusiones
Al usar este patrón estaremos cumpliendo 2 principios de SOLID que son: el principio de Responsabilidad única y el principio de Abierto y Cerrado, lo cual nos ayudará mucho cuando deseamos extender y/o añadir nuevas funcionalidades a nuestras clases sin mayores dolores de cabeza
1 Comment