Menu
Coddy logo textTech

Pattern Strategy

Fa parte della sezione Programmazione orientata agli oggetti del percorso PHP di Coddy. Lezione 74 di 91.

Lo Strategy Pattern è un pattern di progettazione comportamentale che ti permette di definire una famiglia di algoritmi, incapsulare ciascuno nella propria classe e renderli intercambiabili a runtime. L'oggetto che usa la strategia non ha bisogno di sapere quale algoritmo sta eseguendo.

Immagina un carrello della spesa che può applicare diverse strategie di sconto. Invece di codificare direttamente la logica degli sconti con istruzioni condizionali, definisci ogni sconto come una classe separata:

<?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 classe contesto accetta qualsiasi strategia e delega il calcolo:

<?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);

Output:

100
80

Il pattern Strategy è ideale quando hai diversi modi per eseguire un'operazione e vuoi passare da uno all'altro senza modificare la classe che li utilizza. Aggiungere un nuovo tipo di sconto significa creare una nuova classe, senza toccare il codice esistente.

challenge icon

Sfida

Facile

Costruiamo un calcolatore dei costi di spedizione usando lo Strategy Pattern. I diversi metodi di spedizione hanno regole di prezzo diverse: la spedizione standard applica una tariffa fissa, quella express aggiunge una percentuale e quella overnight combina entrambe. Lo Strategy Pattern ti consente di sostituire questi calcoli senza modificare il codice che li utilizza.

Organizzerai il codice in quattro file:

  • ShippingStrategy.php: crea un'interfaccia ShippingStrategy che definisce il contratto per tutti i metodi di spedizione. Dovrebbe avere un metodo calculate(float $weight): float che accetta il peso del pacco e restituisce il costo di spedizione.
  • ShippingMethods.php: includi il file ShippingStrategy e crea tre classi che implementano l'interfaccia:
    • StandardShipping: applica una tariffa fissa di $5.00 indipendentemente dal peso
    • ExpressShipping: applica un costo di $2.00 per chilogrammo (moltiplica il peso per 2)
    • OvernightShipping: applica una tariffa base di $10.00 più $3.00 per chilogrammo
  • ShippingCalculator.php: includi il file ShippingStrategy e crea una classe ShippingCalculator che funge da contesto. Il tuo calcolatore dovrebbe:
    • Accettare un ShippingStrategy nel costruttore (usa la promozione delle proprietà del costruttore)
    • Avere un metodo setStrategy(ShippingStrategy $strategy): void per cambiare il metodo di spedizione durante l'esecuzione
    • Avere un metodo calculateCost(float $weight): float che delega alla strategia corrente
  • main.php: includi i file ShippingMethods e ShippingCalculator. Riceverai due input: un tipo di spedizione ("standard", "express" o "overnight") e il peso di un pacco.

    Crea un ShippingCalculator che inizialmente utilizzi StandardShipping. In base al tipo di spedizione inserito, usa setStrategy() per passare al metodo di spedizione appropriato. Poi calcola il costo per il peso indicato e stampa il risultato formattato con due cifre decimali.

    L'output dovrebbe essere: Shipping cost: $[cost]

Questa sfida mostra come lo Strategy Pattern renda flessibile il tuo sistema di spedizione: per aggiungere un nuovo metodo di spedizione come SameDayShipping basta creare una nuova classe che implementa l'interfaccia, senza modificare il calcolatore o i metodi di spedizione esistenti.

Provalo tu

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

// Leggi l'input
$shippingType = trim(fgets(STDIN));
$weight = floatval(fgets(STDIN));

// TODO: Crea un ShippingCalculator iniziando con StandardShipping

// TODO: In base al tipo di spedizione inserito ("standard", "express" o "overnight"),
// usa setStrategy() per passare al metodo di spedizione appropriato

// TODO: Calcola il costo per il peso indicato

// TODO: Stampa il risultato formattato con due cifre decimali
// Formato dell'output: Shipping cost: $[cost]

?>
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore PHP online