Le pattern Decorator
Description
Le but du pattern Decorator est d’ajouter dynamiquement des fonctionnalités supplémentaires à un objet. Cet ajout de fonctionnalités ne modifie pas l’interface de l’objet et reste donc transparent vis-à-vis des clients.
Le pattern Decorator constitue une alternative par rapport à la création d’une sous-classe pour enrichir un objet.
Exemple
Le système de vente de véhicules dispose d’une classe VueCatalogue qui affiche, sous la forme d’un catalogue électronique, les véhicules disponibles sur une page web.
Nous voulons maintenant afficher des données supplémentaires pour les véhicules "haut de gamme", à savoir les informations techniques liées au modèle. Pour réaliser l’ajout de cette fonctionnalité, nous pouvons réaliser une sous-classe d’affichage spécifique pour les véhicules "haut de gamme". Maintenant, nous voulons afficher le logo de la marque des véhicules "moyen et haut de gamme". Il convient alors d’ajouter une nouvelle sous-classe pour ces véhicules, surclasse de la classe des véhicules "haut de gamme", ce qui devient vite complexe.
Il est aisé de comprendre ici que l’utilisation de l’héritage n’est pas adaptée à ce qui est demandé pour deux raisons :
-
L’héritage est un outil trop puissant pour réaliser un tel ajout de fonctionnalité.
-
L’héritage est un mécanisme statique.
Le pattern Decorator propose une autre approche qui consiste à ajouter un nouvel objet appelé décorateur qui se substitue à l’objet initial et qui le référence....
Structure
1. Diagramme de classes
La figure 3-5.4 détaille la structure générique du pattern.
Figure 3-5.4 - Structure du pattern Decorator
2. Participants
Les participants au pattern sont les suivants :
-
ComposantAbstrait (ComposantGraphiqueVéhicule) est l’interface commune au composant et aux décorateurs.
-
ComposantConcret (VueVéhicule) est l’objet initial auquel de nouvelles fonctionnalités doivent être ajoutées.
-
Décorateur est une classe abstraite qui détient une référence vers un composant.
-
DécorateurConcretA et DécorateurConcretB (ModèleDécorateuret MarqueDécorateur) sont des sous-classes concrètes de Décorateur qui ont pour but l’implantation des fonctionnalités ajoutées au composant.
3. Collaborations
Le décorateur se substitue au composant. Lorsqu’il reçoit un message destiné à ce dernier, il le redirige au composant en effectuant des opérations préalables ou postérieures à cette redirection.
Domaines d’application
Le pattern Decorator peut être utilisé dans les domaines suivants :
-
Un système ajoute dynamiquement des fonctionnalités à un objet, sans modifier son interface, c’est-à-dire sans que les clients de cet objet doivent être modifiés.
-
Un système gère des fonctionnalités qui peuvent être retirées dynamiquement.
-
L’utilisation de l’héritage pour étendre des objets n’est pas pratique, ce qui peut arriver quand leur hiérarchie est déjà complexe.
Exemple en Java
Nous présentons le code source Java de l’exemple, en commençant par l’interface ComposantGraphiqueVehicule.
public interface ComposantGraphiqueVehicule
{
void affiche();
}
La classe VueVehicule implante la méthode affiche de l’interface ComposantGraphiqueVehicule.
public class VueVehicule implements
ComposantGraphiqueVehicule
{
public void affiche()
{
System.out.println("Affichage du véhicule");
}
}
La classe Decorateur implante également la méthode affiche en déléguant l’appel. Elle détient un attribut qui contient une référence vers un composant. Ce dernier est passé en paramètre au constructeur de Decorateur.
public abstract class Decorateur implements
ComposantGraphiqueVehicule
{
protected ComposantGraphiqueVehicule composant;
public Decorateur(ComposantGraphiqueVehicule composant)
{
this.composant = composant;
}
public void affiche()
{
composant.affiche();
}
}
La méthode affiche du décorateur...