Compositions et variations de design patterns
Préliminaire
Les vingt-trois design patterns introduits dans cet ouvrage ne constituent bien évidemment pas une liste exhaustive. Il est possible de créer de nouveaux design patterns soit ex nihilo, soit en composant ou adaptant des design patterns existants. Ces nouveaux design patterns peuvent avoir une portée générale, à l’image de ceux introduits dans les chapitres précédents ou être spécifiques à un environnement de développement particulier.
Dans ce chapitre, nous allons vous montrer trois nouveaux design patterns obtenus par composition et variation de design patterns existants.
Le design pattern Pluggable Factory
1. Introduction
Nous avons introduit dans un précédent chapitre le design pattern Abstract Factory pour abstraire la création (instanciation) de produits de leurs différentes familles. Une fabrique est alors associée à chaque famille de produits. Sur le diagramme de la figure 29.1, deux produits sont exposés : les automobiles et les scooters, décrits chacun par une classe abstraite. Ces produits sont organisés en deux familles : traction à essence et traction à l’électricité. Chacune de ces deux familles engendre une sous-classe concrète de chaque classe de produit.
Il existe donc deux fabriques pour les familles FabriqueVehiculeEssence et FabriqueVehiculeElectricite. Chaque fabrique permet de créer l’un des deux produits à l’aide des méthodes appropriées.
Ce design pattern organise de façon très structurée la création d’objets. Chaque nouvelle famille de produits oblige à ajouter une nouvelle fabrique et donc une nouvelle classe.
À l’opposé, le design pattern Prototype introduit dans le chapitre du même nom offre la possibilité de créer des nouveaux objets de façon très souple.
Figure 29.1 - Exemple d’utilisation du design pattern Abstract Factory
La structure du design pattern Prototype est décrite à la figure 29.2. Un objet initialisé afin d’être prêt à l’emploi et détenant la capacité de se dupliquer est appelé un prototype.
Le client dispose d’une liste de prototypes qu’il peut dupliquer lorsqu’il le désire. Cette liste est construite dynamiquement et peut être modifiée à tout moment lors de l’exécution. Le client peut ainsi construire de nouveaux objets sans connaître la hiérarchie de classes dont ils proviennent.
Figure 29.2 - Exemple d’utilisation du design pattern Prototype
L’idée du design pattern Pluggable Factory est de composer ces deux design patterns pour conserver l’idée de création d’un produit par l’invocation d’une méthode de la fabrique et d’autre part, de pouvoir changer dynamiquement la famille à créer. Ainsi...
Le design pattern Reflective Visitor
1. Discussion
Nous vous avons présenté dans un chapitre précédent le design pattern Visitor dont le but est de pouvoir ajouter de nouvelles fonctionnalités à un ensemble de classes sans devoir modifier ces classes à chaque ajout. Chaque nouvelle fonctionnalité donne lieu à une classe de visiteur qui implémente cette fonctionnalité en introduisant un ensemble de méthodes, une pour chaque classe. Toutes ces méthodes ont pour nom visite suivi du nom de la classe pour laquelle la fonctionnalité est implémentée.
Toutefois, pour implémenter le design pattern Visitor, les classes devant être visitées subissent une légère modification, à savoir l’introduction d’une méthode pour accepter le visiteur, méthode dont le seul but est d’invoquer la méthode dont le nom est visite suivi du nom de la classe à visiter. Le nom de cette méthode est souvent accepte ou accepteVisiteur.
La figure 29.5 montre une mise en œuvre du design pattern Visitor dans le but de visiter une hiérarchie d’objets décrite à l’aide du design pattern Composite. Ces objets sont des sociétés dont certaines, les sociétés mères, possèdent des filiales. Les deux fonctionnalités ajoutées sont le calcul des coûts d’entretien et la possibilité d’envoi d’un mailing commercial à une société en incluant toutes ses filiales, y compris les filiales des filiales. La méthode accepteVisiteur de la classe SocieteMere inclut une boucle foreach demandant à chacune des filiales d’accepter à son tour le visiteur.
Figure 29.5 - Application du design pattern Visitor à un ensemble de sociétés
Le design pattern Reflective Visitor est une variante de Visitor qui utilise la capacité de réflexion structurelle du langage de programmation afin que la mise en œuvre ne nécessite pas l’introduction de la méthode d’acceptation du visiteur dans les classes devant être visitées. La réflexion structurelle d’un langage de programmation est sa capacité à fournir un moyen d’examiner l’ensemble...
Le design pattern Multicast
1. Description et exemple
Le but du design pattern Multicast est de gérer les événements produits dans un programme afin de les transmettre à un ensemble de récepteurs concernés. Ce design pattern est basé sur un mécanisme d’inscription des récepteurs auprès des expéditeurs.
Nous voulons mettre en œuvre un programme d’envoi de messages entre les directions (générale, commerciale, financière, etc.) d’un concessionnaire et ses employés.
Chaque employé peut s’inscrire auprès de la direction à laquelle il appartient et recevoir ainsi tous les messages émis par cette dernière. Un employé ne peut pas s’inscrire auprès d’une direction à laquelle il n’appartient pas. Tous les employés peuvent bien sûr s’inscrire auprès de la direction générale afin d’en recevoir les messages.
La structure des messages peut varier d’une direction à l’autre : simple ligne de texte pour les messages commerciaux, liste de lignes pour les messages généraux provenant de la direction générale.
Le diagramme de classes de la figure 29.8 expose la solution proposée par le design pattern Multicast. La classe concrète Expediteur introduit des objets chargés d’expédier un message à un ensemble de récepteurs. Le message est typé par l’interface MessageAbstrait tandis que le récepteur est typé par l’interface RecepteurAbstrait.
Figure 29.8 - Le design pattern Multicast appliqué à un système de messages
La classe Expediteur présente deux fonctionnalités :
-
Elle gère un registre (une liste) de récepteurs avec la possibilité d’y inscrire un nouveau récepteur grâce à la méthode ajoute.
-
Elle permet d’envoyer un message à l’ensemble des récepteurs présents dans le registre grâce à la méthode envoieMultiple.
L’interface MessageAbstraitInterface introduit la signature de la méthode afficheContenu qui a pour objet d’afficher le contenu du message. L’interface RecepteurAbstraitInterface expose la signature...