Menu
Coddy logo textTech

Patron Strategy

Fait partie de la section Programmation Orientée Objet du Journey PHP de Coddy. Leçon 74 sur 91.

Le pattern Strategy est un patron de conception comportemental qui vous permet de définir une famille d’algorithmes, d’encapsuler chacun d’eux dans sa propre classe et de les rendre interchangeables à l’exécution. L’objet qui utilise la stratégie n’a pas besoin de savoir quel algorithme il exécute.

Imaginez un panier d’achat qui peut appliquer différentes stratégies de réduction. Au lieu de coder en dur la logique des réductions avec des conditions, vous définissez chaque réduction comme une classe distincte :

<?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 de contexte accepte n’importe quelle stratégie et délègue le calcul :

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

Sortie :

100
80

Le pattern Strategy est particulièrement utile lorsque vous disposez de plusieurs façons d’effectuer une opération et que vous souhaitez passer de l’une à l’autre sans modifier la classe qui les utilise. Ajouter un nouveau type de remise signifie créer une nouvelle classe, sans toucher au code existant.

challenge icon

Défi

Facile

Construisons un calculateur de frais d’expédition à l’aide du patron Strategy. Les différentes méthodes d’expédition ont des règles de tarification différentes : l’expédition standard facture un tarif fixe, l’expédition express ajoute un pourcentage et l’expédition de nuit combine les deux. Le patron Strategy vous permet de remplacer ces calculs sans modifier le code qui les utilise.

Vous organiserez votre code sur quatre fichiers :

  • ShippingStrategy.php : créez une interface ShippingStrategy qui définit le contrat pour toutes les méthodes d’expédition. Elle doit disposer d’une méthode calculate(float $weight): float qui prend le poids du colis et renvoie le coût de l’expédition.
  • ShippingMethods.php : incluez le fichier ShippingStrategy et créez trois classes qui implémentent l’interface :
    • StandardShipping : facture un tarif fixe de $5.00, quel que soit le poids
    • ExpressShipping : facture $2.00 par kilogramme (multipliez le poids par 2)
    • OvernightShipping : facture des frais de base de $10.00 plus $3.00 par kilogramme
  • ShippingCalculator.php : incluez le fichier ShippingStrategy et créez une classe ShippingCalculator qui joue le rôle de contexte. Votre calculateur doit :
    • Accepter un ShippingStrategy dans son constructeur (utilisez la promotion du constructeur)
    • Disposer d’une méthode setStrategy(ShippingStrategy $strategy): void pour modifier la méthode d’expédition au moment de l’exécution
    • Disposer d’une méthode calculateCost(float $weight): float qui délègue le calcul à la stratégie actuelle
  • main.php : incluez les fichiers ShippingMethods et ShippingCalculator. Vous recevrez deux entrées : un type d’expédition ("standard", "express" ou "overnight") et le poids d’un colis.

    Créez un ShippingCalculator en commençant par StandardShipping. En fonction de l’entrée correspondant au type d’expédition, utilisez setStrategy() pour passer à la méthode d’expédition appropriée. Calculez ensuite le coût pour le poids donné et affichez le résultat avec deux décimales.

    La sortie doit être : Shipping cost: $[cost]

Ce défi montre comment le patron Strategy rend votre système d’expédition flexible : l’ajout d’une nouvelle méthode d’expédition comme SameDayShipping nécessite uniquement de créer une nouvelle classe qui implémente l’interface, sans modifier le calculateur ni les méthodes d’expédition existantes.

Essayez vous-même

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

// Lire l'entrée
$shippingType = trim(fgets(STDIN));
$weight = floatval(fgets(STDIN));

// TODO: Créer un ShippingCalculator en commençant avec StandardShipping

// TODO: En fonction du type d'expédition en entrée ("standard", "express", ou "overnight"),
// utiliser setStrategy() pour basculer vers la méthode d'expédition appropriée

// TODO: Calculer le coût pour le poids donné

// TODO: Afficher le résultat formaté à deux décimales
// Output format: Shipping cost: $[cost]

?>
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet

Entraînez-vous par vous-même : Compilateur PHP en ligne