Blog ENI : Toute la veille numérique !
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
💥 Du 22 au 24 novembre : Accès 100% GRATUIT
à la Bibliothèque Numérique ENI. Je m'inscris !
  1. Livres et vidéos
  2. Design Patterns en PHP
  3. Le design pattern State
Extrait - Design Patterns en PHP Les 23 modèles de conception : descriptions et solutions illustrées en UML2 et PHP (2e édition)
Extraits du livre
Design Patterns en PHP Les 23 modèles de conception : descriptions et solutions illustrées en UML2 et PHP (2e édition)
2 avis
Revenir à la page d'achat du livre

Le design pattern State

Description

Le design pattern State permet à un objet d’adapter son comportement en fonction de son état interne.

Exemple

Nous nous intéressons aux commandes de produits sur notre site de vente en ligne. Elles sont décrites par la classe Commande. Les instances de cette classe possèdent un cycle de vie qui est illustré par le diagramme d’états-transitions de la figure 25.1. L’état EnCours est l’état où la commande est en cours de constitution : le client ajoute des produits. L’état Validée est l’état où la commande a été validée et réglée par le client. Enfin, l’état Livrée est l’état où les produits ont été livrés.

Diagramme d’états-transitions d’une commande

Figure 25.1 - Diagramme d’états-transitions d’une commande

La classe Commande possède des méthodes dont le comportement diffère en fonction de cet état. Par exemple, la méthode ajouteProduit n’ajoute des produits que si la commande se trouve dans l’état EnCours. De même, la méthode efface n’a pas de comportement dans les états Livrée et Validée.

L’approche traditionnelle pour résoudre ces différences de comportement consiste à utiliser des branchements conditionnels dans le corps des méthodes. Cette approche conduit souvent à des méthodes complexes à écrire et à maintenir, noyées...

Structure

1. Diagramme de classes

La figure 25.3 illustre la structure générique du design pattern State.

Structure du design pattern State

Figure 25.3 - Structure du design pattern State

2. Participants

Les participants au design pattern State sont les suivants :

  • MachineEtat (Commande) est une classe concrète décrivant des objets qui sont des machines à états, c’est-à-dire qui possèdent un ensemble d’états pouvant être décrit par un diagramme d’états-transitions. Cette classe détient une référence vers une instance d’une sous-classe d’Etat qui définit l’état courant.

  • Etat (AbstractEtatCommande) est une classe abstraite qui introduit la signature des méthodes liées à l’état et qui gère l’association avec la machine à états.

  • EtatConcretAet EtatConcretB (CommandeEnCours, CommandeValidee et CommandeLivree) sont des sous-classes concrètes qui implémentent le comportement des méthodes relativement à chaque état.

3. Collaborations

La machine à états délègue les appels des méthodes dépendant de l’état courant vers un objet d’état.

La machine à états peut transmettre à l’objet d’état une référence vers elle-même si c’est nécessaire....

Domaines d’application

Le design pattern State est utilisé dans les cas suivants :

  • Le comportement d’un objet dépend de son état.

  • L’implémentation de cette dépendance à l’état par des branchements conditionnels s’avère trop complexe.

Exemple en PHP

Nous présentons l’exemple de la figure 25.2 en PHP. La classe Commande est décrite à la suite. Les méthodes ajouteProduit, retireProduit et efface dépendent de l’état. Par conséquent leur implémentation consiste à appeler la méthode correspondante de l’instance référencée par etatCommande.

Le constructeur de la classe initialise l’attribut etatCommande avec une instance de la classe CommandeEnCours. La méthode etatSuivant passe à l’état suivant en associant une nouvelle instance à l’attribut etatCommande

<?php 
 
declare(strict_types=1); 
 
namespace ENI\DesignPatterns\State; 
 
class Commande 
{ 
   protected array $produits = []; 
 
   protected AbstractEtatCommande $etatCommande; 
 
   public function __construct() 
   { 
       $this->etatCommande = new CommandeEnCours($this); 
   } 
 
   public function getProduits(): array 
   { 
       return $this->produits; 
   } 
 
   public function effaceProduits(): void 
   { 
       $this->produits = []; 
   } 
 
   public function rajoute(Produit $produit): void 
   { 
       $this->produits[] = $produit; 
   } 
 
   public function ajouteProduit(Produit $produit): void 
   { 
       $this->etatCommande->ajouteProduit($produit); 
   } 
 
   public function retireProduit(Produit $produit): void 
   { 
       $this->etatCommande->retireProduit($produit); 
   } 
 
   public function efface(): void 
   { 
       $this->etatCommande->efface(); 
   } 
 
   public...