Le design pattern Chain of Responsibility
Description
Le design pattern Chain of Responsibility construit une chaîne d’objets telle que si un objet de la chaîne ne peut pas répondre favorablement à une requête, il la transmette à son successeur et ainsi de suite jusqu’à ce que l’un des objets de la chaîne y réponde.
Exemple
Nous nous plaçons dans le cadre de la vente de véhicules d’occasion. Lorsque le catalogue de ces véhicules est affiché, l’utilisateur peut demander une description de l’un des véhicules mis en vente. Si une telle description n’a pas été fournie, le système doit alors renvoyer la description associée au modèle de ce véhicule. Si, à nouveau, cette description du modèle n’a pas été fournie, il convient de renvoyer la description associée à la marque du véhicule. Une description par défaut est renvoyée s’il n’y a pas non plus de description associée à la marque.
Ainsi, l’utilisateur reçoit en priorité la description la plus précise qui est disponible dans le système.
Le design pattern Chain of Responsibility fournit une solution pour mettre en œuvre ce mécanisme. Celle-ci consiste à lier les objets entre eux du plus spécifique (le véhicule) au plus général (la marque) pour former la chaîne de responsabilité qui a donné son nom au design pattern. La requête de description est transmise le long de cette chaîne jusqu’à ce qu’un objet puisse la traiter et renvoyer la description.
Le diagramme d’objets UML de la figure 18.1 illustre...
Structure
1. Diagramme de classes
La figure 18.4 détaille la structure générique du design pattern Chain of Responsibility.
Figure 18.4 - Structure du design pattern Chain of Responsibility
2. Participants
Les participants au design patter Chain of Responsibility sont les suivants :
-
Gestionnaire (AbstractObjetBase) est une classe abstraite qui implémente sous la forme d’une association la chaîne de responsabilité ainsi que l’interface des requêtes.
-
GestionnaireConcret1 et GestionnaireConcret2 (Vehicule, Modele et Marque) sont les classes concrètes qui implémentent le traitement des requêtes en utilisant la chaîne de responsabilité si elles ne peuvent pas les traiter.
-
Client (Utilisateur) déclenche la requête initiale auprès d’un objet de l’une des classes GestionnaireConcret1 ou GestionnaireConcret2.
3. Collaborations
Le client effectue la requête initiale auprès d’un gestionnaire. Cette requête est propagée le long de la chaîne de responsabilité jusqu’au moment où l’un des gestionnaires la traite.
Domaines d’application
Le design pattern Chain of Responsibility est utilisé dans les cas suivants :
-
Une chaîne d’objets gère une requête selon un ordre qui est défini dynamiquement.
-
La façon dont une chaîne d’objets gère une requête ne doit pas être connue de ses clients.
Exemple en PHP
Voyons maintenant l’exemple en langage PHP. La classe abstraite AbstractObjetBase est décrite à la suite. Elle implémente la chaîne de responsabilité par le biais de l’attribut suivant dont la valeur peut être fixée par la méthode setSuivant. Les autres méthodes correspondent aux spécifications introduites dans la figure 18.2.
<?php
declare(strict_types=1);
namespace ENI\DesignPatterns\ChainOfResponsibility;
abstract class AbstractObjetBase
{
protected self $suivant;
public function donneDescription(): string
{
$resultat = $this->getDescription();
if (!empty($resultat)) {
return $resultat . PHP_EOL;
}
if (isset($this->suivant)) {
return $this->suivant->donneDescription();
} else {
return $this->descriptionParDefaut() . PHP_EOL;
}
}
public function setSuivant(self $suivant): void
{
$this->suivant = $suivant;
}
private function descriptionParDefaut(): string
{ ...