Le design pattern Strategy
Description
Le design pattern Strategy consiste à encapsuler une famille d’algorithmes dans des objets dédiés de manière à ce qu’une classe cliente puisse définir dynamiquement ceux qu’elle souhaite utiliser et, le cas échéant, les permuter sans compromettre le bon déroulement de l’exécution du code.
Ce besoin peut relever de plusieurs aspects comme des aspects de présentation, d’efficacité en temps d’exécution ou en mémoire, de choix d’algorithmes, de représentation interne, etc. Mais évidemment, il ne s’agit pas d’un besoin fonctionnel vis-à-vis des clients de l’objet car les interactions entre l’objet et ses clients doivent rester inchangées.
Exemple
Dans le système de vente en ligne de véhicules, la classe VueCatalogue dessine la liste des véhicules destinés à la vente. Un algorithme de dessin est utilisé pour calculer la mise en page en fonction du navigateur. Il existe deux versions de cet algorithme :
-
Une première version qui n’affiche qu’un seul véhicule par ligne (un véhicule prend toute la largeur disponible) et qui affiche le maximum d’informations ainsi que quatre photos.
-
Une seconde version qui affiche trois véhicules par ligne mais qui affiche moins d’informations et une seule photo.
L’interface de la classe VueCatalogue ne dépend pas du choix de l’algorithme de mise en page. Ce choix n’a pas d’impact sur la relation d’une vue de catalogue avec ses clients. Il n’y a que la présentation qui est modifiée.
Une première solution consiste à transformer la classe VueCatalogue en une interface ou en une classe abstraite et à introduire deux sous-classes d’implémentation différant par le choix de l’algorithme. Ceci présente l’inconvénient de complexifier inutilement la hiérarchie des vues de catalogue.
Une autre possibilité est d’implémenter les deux algorithmes dans la classe VueCatalogue et à l’aide d’instructions conditionnelles...
Structure
1. Diagramme de classes
La figure 26.2 montre la structure générique du design pattern Strategy.
Figure 26.2 - Structure du design pattern Strategy
2. Participants
Les participants au design pattern Strategy sont les suivants :
-
Strategie (DessinCatalogueInterface) est l’interface commune à tous les algorithmes. Cette interface est utilisée par Entite pour invoquer l’algorithme.
-
StrategieConcreteA et StrategieConcreteB (DessinUnVehiculeLigne et DessinTroisVehiculesLigne) sont les sous-classes concrètes qui implémentent les différents algorithmes.
-
Entite est la classe utilisant un des algorithmes des classes d’implémentation de Strategie. En conséquence, elle possède une référence vers une instance de l’une de ces classes. Enfin, si nécessaire, elle peut exposer ses données internes aux classes d’implémentation.
3. Collaborations
L’entité et les instances des classes d’implémentation de Strategie interagissent pour implémenter les algorithmes. Dans le cas le plus simple, les données nécessaires à l’algorithme sont transmises en paramètre. Si nécessaire, la classe Entite implémentera des méthodes pour donner accès à ses propriétés.
Le client initialise l’entité avec une instance de la classe d’implémentation...
Domaines d’application
Le design pattern Strategy est utilisé dans les cas suivants :
-
Le comportement d’une classe peut être implémenté par différents algorithmes dont certains sont plus efficaces en temps d’exécution ou moins gourmands en mémoire.
-
L’implémentation du choix de l’algorithme par des instructions conditionnelles est trop complexe.
-
Un système possède de nombreuses classes identiques à l’exception d’une partie de leur comportement.
Dans le dernier cas, le design pattern Strategy permet de regrouper ces classes en une seule, ce qui simplifie l’interface pour les clients.
Exemple en PHP
Notre exemple en PHP est basé sur l’affichage du catalogue de véhicules, simulé ici simplement avec des sorties à l’écran.
L’interface DessinCatalogueInterface contient la méthode dessine qui prend en paramètre une liste d’instances de VueVehicule.
<?php
declare(strict_types=1);
namespace ENI\DesignPatterns\Strategy;
interface DessinCatalogueInterface
{
public function dessine(ListeVueVehicule $listeVueVehicule): void;
}
La classe ListeVueVehicule facilite la gestion d’une liste d’objets de la classe VueVehicule en PHP. Son code est donné à la suite.
<?php
declare(strict_types=1);
namespace ENI\DesignPatterns\Strategy;
class ListeVueVehicule
{
protected array $vuesVehicule = [];
public function getVues(): array
{
return $this->vuesVehicule;
}
public function ajoute(VueVehicule $vue): void
{
$this->vuesVehicule[] = $vue;
}
}
La classe DessinUnVehiculeLigne implémente la méthode dessine en affichant chaque véhicule sur une ligne (impression d’un saut de ligne après l’affichage d’un véhicule).
<?php
declare(strict_types=1);
namespace ENI\DesignPatterns\Strategy;
class DessinUnVehiculeLigne implements DessinCatalogueInterface
{
public function dessine(ListeVueVehicule...