Menu
Coddy logo textTech

Patrón Strategy

Parte de la sección Programación Orientada a Objetos del Journey de PHP de Coddy. Lección 74 de 91.

El patrón Strategy es un patrón de diseño de comportamiento que te permite definir una familia de algoritmos, encapsular cada uno en su propia clase y hacer que sean intercambiables durante la ejecución. El objeto que utiliza la estrategia no necesita saber qué algoritmo está ejecutando.

Imagina un carrito de compras que puede aplicar diferentes estrategias de descuento. En lugar de codificar directamente la lógica de descuento con condicionales, defines cada descuento como una clase independiente:

<?php
interface DiscountStrategy {
    public function calculate(float $total): float;
}

class NoDiscount implements DiscountStrategy {
    public function calculate(float $total): float {
        return $total;
    }
}

class PercentageDiscount implements DiscountStrategy {
    public function __construct(private int $percent) {}
    
    public function calculate(float $total): float {
        return $total - ($total * $this->percent / 100);
    }
}

class FixedDiscount implements DiscountStrategy {
    public function __construct(private float $amount) {}
    
    public function calculate(float $total): float {
        return max(0, $total - $this->amount);
    }
}

La clase de contexto acepta cualquier estrategia y delega el cálculo:

<?php
class ShoppingCart {
    public function __construct(private DiscountStrategy $discount) {}
    
    public function setDiscount(DiscountStrategy $discount): void {
        $this->discount = $discount;
    }
    
    public function checkout(float $total): float {
        return $this->discount->calculate($total);
    }
}

$cart = new ShoppingCart(new NoDiscount());
echo $cart->checkout(100) . "\n";

$cart->setDiscount(new PercentageDiscount(20));
echo $cart->checkout(100);

Salida:

100
80

El patrón Strategy destaca cuando tienes varias formas de realizar una operación y quieres cambiar entre ellas sin modificar la clase que las utiliza. Añadir un nuevo tipo de descuento significa crear una nueva clase, no modificar el código existente.

challenge icon

Desafío

Fácil

Construyamos una calculadora de costos de envío utilizando el patrón Strategy. Los diferentes métodos de envío tienen distintas reglas de precios: el envío estándar cobra una tarifa fija, el envío exprés añade un porcentaje y el envío nocturno combina ambos. El patrón Strategy te permite intercambiar estos cálculos sin cambiar el código que los utiliza.

Organizarás tu código en cuatro archivos:

  • ShippingStrategy.php: Crea una interfaz ShippingStrategy que defina el contrato para todos los métodos de envío. Debe tener un método calculate(float $weight): float que reciba el peso del paquete y devuelva el costo de envío.
  • ShippingMethods.php: Incluye el archivo ShippingStrategy y crea tres clases que implementen la interfaz:
    • StandardShipping: Cobra una tarifa fija de $5.00 independientemente del peso
    • ExpressShipping: Cobra $2.00 por kilogramo (multiplica el peso por 2)
    • OvernightShipping: Cobra una tarifa base de $10.00 más $3.00 por kilogramo
  • ShippingCalculator.php: Incluye el archivo ShippingStrategy y crea una clase ShippingCalculator que actúe como contexto. Tu calculadora debe:
    • Aceptar un ShippingStrategy en su constructor (utiliza la promoción del constructor)
    • Tener un método setStrategy(ShippingStrategy $strategy): void para cambiar el método de envío en tiempo de ejecución
    • Tener un método calculateCost(float $weight): float que delegue en la estrategia actual
  • main.php: Incluye los archivos ShippingMethods y ShippingCalculator. Recibirás dos entradas: un tipo de envío ("standard", "express" u "overnight") y el peso de un paquete.

    Crea un ShippingCalculator que comience con StandardShipping. Según la entrada del tipo de envío, utiliza setStrategy() para cambiar al método de envío adecuado. Después, calcula el costo para el peso indicado e imprime el resultado con dos decimales.

    La salida debe ser: Shipping cost: $[cost]

Este desafío demuestra cómo el patrón Strategy hace flexible tu sistema de envíos: añadir un nuevo método de envío, como SameDayShipping, solo requiere crear una nueva clase que implemente la interfaz, sin modificar la calculadora ni los métodos de envío existentes.

Pruébalo tú mismo

<?php
require_once 'ShippingMethods.php';
require_once 'ShippingCalculator.php';

// Leer entrada
$shippingType = trim(fgets(STDIN));
$weight = floatval(fgets(STDIN));

// TODO: Crea un ShippingCalculator empezando con StandardShipping

// TODO: Basado en la entrada del tipo de envío ("standard", "express" o "overnight"),
// usa setStrategy() para cambiar al método de envío apropiado

// TODO: Calcula el costo para el peso dado

// TODO: Imprime el resultado formateado a dos decimales
// Output format: Shipping cost: $[cost]

?>
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de PHP online