🚨 ¡Nueva review! ¡Mi teclado ideal! ⌨️ Perfecto para programar, el Logitech MX Keys S . ¡Échale un ojo! 👀

El patrón de diseño Strategy

El arte de intercambiar comportamientos como piezas de Lego

Escrito por domin el 18 de noviembre de 2025

♟️ 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.

Diagrama del patrón Strategy mostrando un contexto que utiliza una interfaz para delegar comportamiento.

🤯 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:

Concepto (analogía)

Rol en Strategy

Tarea principal

El Carrito de ComprasContexto

Delega el pago a la estrategia que tenga configurada.

PayPal, Tarjeta, BizumEstrategias Concretas

Contienen la lógica real (ejecutarPago).

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)

2. Estrategias concretas

3. El contexto

✨ 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í)

⚠️ Luz roja (no)

📈 6. Beneficios clave

  1. Mantenibilidad: Añadir un nuevo método de pago no afecta al código del carrito.
  2. Flexibilidad: Puedes cambiar cómo se comporta el objeto mientras el programa está corriendo.
  3. 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 🍻