Menu
Coddy logo textTech

Patron Stratégie

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

Le Strategy Pattern (ou patron de conception Stratégie) 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 au moment de l'exécution. L'objet utilisant la stratégie n'a pas besoin de savoir quel algorithme il exécute.

Imaginez un panier d'achat capable d'appliquer différentes stratégies de remise. Au lieu de coder en dur la logique de remise avec des conditions, vous définissez chaque remise 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 brille lorsque vous avez plusieurs façons d'effectuer une opération et que vous souhaitez basculer entre elles 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 en utilisant le Strategy Pattern. Différentes méthodes d'expédition ont des règles de tarification différentes — l'expédition standard facture un tarif forfaitaire, l'expédition express ajoute un pourcentage, et l'expédition de nuit combine les deux. Le Strategy Pattern vous permet d'interchanger 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 avoir une méthode calculate(float $weight): float qui prend le poids du colis et retourne le coût d'expédition.
  • ShippingMethods.php — Incluez le fichier ShippingStrategy et créez trois classes qui implémentent l'interface :
    • StandardShipping — Facture un tarif forfaitaire 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 agit comme contexte. Votre calculateur doit :
    • Accepter une ShippingStrategy dans son constructeur (utilisez la promotion de constructeur)
    • Avoir une méthode setStrategy(ShippingStrategy $strategy): void pour changer la méthode d'expédition au moment de l'exécution
    • Avoir une méthode calculateCost(float $weight): float qui délègue à 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 un poids de colis.

    Créez un ShippingCalculator en commençant par StandardShipping. En fonction du type d'expédition saisi, 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 formaté avec deux décimales.

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

Ce défi démontre comment le Strategy Pattern rend votre système d'expédition flexible — l'ajout d'une nouvelle méthode d'expédition comme SameDayShipping nécessite seulement la création d'une nouvelle classe qui implémente l'interface, sans toucher au calculateur ou aux méthodes d'expédition existantes.

Aide-mémoire

Le Strategy Pattern (ou patron de stratégie) est un patron de conception comportemental qui définit une famille d'algorithmes, encapsule chacun d'eux dans sa propre classe et les rend interchangeables au moment de l'exécution.

Définissez une interface pour la stratégie :

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

Implémentez des stratégies concrètes :

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

Créez une classe de contexte qui utilise la stratégie :

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

Utilisez le patron en injectant des stratégies :

<?php
$cart = new ShoppingCart(new NoDiscount());
echo $cart->checkout(100); // 100

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

Le Strategy Pattern vous permet de basculer entre les algorithmes sans modifier la classe qui les utilise. L'ajout de nouvelles stratégies nécessite uniquement la création de nouvelles classes qui implémentent l'interface.

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 par StandardShipping

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

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

// TODO: Afficher le résultat formaté avec deux décimales
// Format de sortie : 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