♟️ El patrón de diseño Strategy
El patrón Strategy es uno de los patrones de comportamiento más elegantes y útiles. Su misión principal es simple: manejar la variación de algoritmos de forma limpia.

🤯 1. El problema que resuelve.
El escenario habitual
Imagina que tienes una clase encargada de una tarea, pero la forma de hacer esa tarea cambia según una condición externa. Lo clásico (y erróneo) es crear un método gigante lleno de if/else o switch para elegir qué camino tomar.
// Código difícil de mantener y acoplado
class CarritoCompras {
public function checkout(string $metodoPago) {
if ($metodoPago === 'paypal') {
// Lógica de PayPal
} else if ($metodoPago === 'tarjeta') {
// Lógica de Tarjeta de Crédito
} else if ($metodoPago === 'bizum') {
// Lógica de Bizum
}
// Si mañana quieres añadir "Apple Pay", tienes que modificar esta clase.
}
}
Esto rompe el principio Open/Close de SOLID: una clase debería estar abierta a extensión (poder añadir nuevos pagos) pero cerrada a modificación (no tener que tocar el método checkout cada vez).
✨ La solución en 60 segundos
El patrón de diseño Strategy arregla esto delegando la lógica a una clase separada.
La idea es: definir una familia de algoritmos, encapsular cada uno y hacerlos intercambiables. El objeto principal ya no “sabe” cómo hacer la tarea, simplemente se la pasa al objeto estrategia que tenga asignado.
🌎 2. Analogía: los métodos de pago
Vamos a ver cómo funciona el proceso de pago en una tienda online:
- El sujeto (el contexto): Es el Carrito de Compras. Su trabajo es saber qué productos llevas y el total. No le importa cómo pagas, solo que pagues.
- La interfaz (la estrategia): Es el Contrato de Pago. Define una norma:
ejecutarPago(monto). - Las implementaciones (estrategias concretas): Son PayPal, Tarjeta o Bizum. Cada uno cumple el contrato a su manera.
Concepto (analogía) | Rol en Strategy | Tarea principal |
|---|---|---|
| El Carrito de Compras | Contexto | Delega el pago a la estrategia que tenga configurada. |
| PayPal, Tarjeta, Bizum | Estrategias Concretas | Contienen la lógica real ( |
La magia está en que el Carrito no conoce a PayPal ni a Bizum, solo conoce la interfaz genérica. Esto desacopla totalmente el código.
🛠️ 3. Los tres pilares del patrón
Para que el Strategy funcione, necesitamos tres actores:
1. La estrategia (interfaz)
- Define el “contrato” común.
- El contexto usa esta interfaz para comunicarse.
2. Estrategias concretas
- Son las clases que implementan la interfaz.
- Aquí vive el código específico (la “chicha”) del algoritmo.
3. El contexto
- Mantiene una referencia a una estrategia.
- Permite cambiar dicha estrategia en tiempo de ejecución (“ahora pago con tarjeta”, “ahora con PayPal”).
- No sabe qué estrategia concreta está usando.
✨ Widget pedagógico: El interruptor de velocidad
Imagina un coche (el contexto) con un método acelerar().
El coche puede tener varios motores intercambiables (estrategias):
eléctrico, diésel o reacción. El coche simplemente llama a
motor.acelerar() , pero el comportamiento real depende del
motor que le hayas instalado.
🤔 1. ¿Qué principio de diseño refuerza el uso del patrón Strategy?
🧑💻 4. El código en PHP
Vamos a implementar el ejemplo del Carrito de Compras.
<?php
// 🔹 1. La Interfaz
interface EstrategiaPago {
// El contrato que todos deben cumplir
public function pagar(float $monto): void;
}
// 🔹 2. Estrategias Concretas (Los algoritmos)
class PagoPayPal implements EstrategiaPago {
public function pagar(float $monto): void {
echo " [PAGO] Pagando $monto€ vía PayPal." . PHP_EOL;
// Aquí iría la conexión real con la API de PayPal
}
}
class PagoTarjetaCredito implements EstrategiaPago {
public function pagar(float $monto): void {
echo " [PAGO] Pagando $monto€ con Tarjeta de Crédito." . PHP_EOL;
// Aquí iría la conexión con la pasarela bancaria
}
}
// 🔹 3. El Contexto
class CarritoCompras {
private EstrategiaPago $estrategiaPago;
private float $montoTotal;
public function __construct(float $monto) {
$this->montoTotal = $monto;
}
// Permite cambiar la estrategia al vuelo
public function setEstrategiaPago(EstrategiaPago $estrategia): void {
$this->estrategiaPago = $estrategia;
echo "--- Cambio de estrategia a: " . get_class($estrategia) . " ---" . PHP_EOL;
}
// Delega el trabajo a la estrategia actual
public function ejecutarPago(): void {
if (!isset($this->estrategiaPago)) {
echo "Error: Elige un método de pago primero." . PHP_EOL;
return;
}
echo "-> El carrito procesa el pago de {$this->montoTotal}€..." . PHP_EOL;
// El Contexto llama al método sin saber quién lo ejecuta realmente
$this->estrategiaPago->pagar($this->montoTotal);
}
}
// 🔹 4. Uso del patrón (Cliente)
$carrito = new CarritoCompras(99.99);
// Creamos las estrategias disponibles
$pagoPaypal = new PagoPayPal();
$pagoTarjeta = new PagoTarjetaCredito();
// Escenario 1: Cliente elige PayPal
$carrito->setEstrategiaPago($pagoPaypal);
$carrito->ejecutarPago();
echo PHP_EOL;
// Escenario 2: Cliente cambia de opinión y paga con Tarjeta
// Fíjate que cambiamos el comportamiento sin tocar el objeto $carrito
$carrito->setEstrategiaPago($pagoTarjeta);
$carrito->ejecutarPago();
// 🖥️ Resultado en consola:
// --- Cambio de estrategia a: PagoPayPal ---
// -> El carrito procesa el pago de 99.99€...
// [PAGO] Pagando 99.99€ vía PayPal.
//
// --- Cambio de estrategia a: PagoTarjetaCredito ---
// -> El carrito procesa el pago de 99.99€...
// [PAGO] Pagando 99.99€ con Tarjeta de Crédito.
✅ 5. ¿Cuándo usarlo y cuándo no?
✅ Luz verde (sí)
- Cuando tienes varias formas de hacer lo mismo y necesitas intercambiarlas dinámicamente.
- Para limpiar clases llenas de condicionales (
if/else) que seleccionan comportamientos. - Para aislar lógica de negocio compleja: cada algoritmo se va a su propia clase y no molesta al resto.
⚠️ Luz roja (no)
- Si tu aplicación es muy simple y solo tienes una o dos variantes que nunca cambian. No mates moscas a cañonazos (sobreingeniería).
- Si las estrategias son tan simples (como una sola línea de cálculo) que crear clases y archivos nuevos ensucia más que limpia.
📈 6. Beneficios clave
- Mantenibilidad: Añadir un nuevo método de pago no afecta al código del carrito.
- Flexibilidad: Puedes cambiar cómo se comporta el objeto mientras el programa está corriendo.
- Orden: Cada clase tiene una única responsabilidad (SRP), lo que facilita los tests y la lectura.
🖼️ 7. Resumen
Strategy es como una herramienta eléctrica con cabezales intercambiables: el motor (contexto) es el mismo, pero según el cabezal (estrategia) que le pongas, puedes taladrar, lijar o pulir.
🤔 2. ¿Cuál es el rol principal del Contexto?
¡EA! Saluditos y nos vemos en los bares 🍻