Patron de conception (Software design pattern)
https://fr.wikipedia.org/wiki/Patron_de_conception
Un patron de conception est issu de l'expérience des concepteurs de logiciels2. Il décrit un arrangement récurrent de rôles et d'actions joués par des modules d'un logiciel, et le nom du patron sert de vocabulaire commun entre le concepteur et le programmeur3. D'une manière analogue à un motif de conception en architecture, le patron de conception décrit les grandes lignes d'une solution, qui peuvent ensuite être modifiées et adaptées en fonction des besoins4.
Les patrons de conception décrivent des procédés de conception généraux et permettent en conséquence de capitaliser l'expérience appliquée à la conception de logiciel. Ils ont une influence sur l'architecture logicielle d'un système informatique.
Le patron proxy.
Sommaire
Types de patrons
Les patrons de conception ne sont ni des patrons d'architecture ni des idiotismes de programmation.- Le patron d'architecture apporte des solutions sur la manière de concevoir l'organisation à grande échelle (architecture) d'un logiciel en faisant abstraction des détails. Il concerne la structure générale d'un logiciel, sa subdivision en unités plus petites, comporte des guides de bonnes pratiques et des règles générales qui ne peuvent pas être traduites directement en code source5.
- Le patron de conception suggère un arrangement, une manière d'organiser des modules ou des classes. Il décrit une organisation de classes fréquemment utilisée pour résoudre un problème récurrent. Le patron de conception parle d'instances, de rôles et de collaboration5.
- L'idiotisme de programmation est une construction spécifique à un langage de programmation,
qui est une manière usuelle de mettre en œuvre une solution à un
problème dans ce langage de programmation. Par exemple pour effectuer
cent fois une opération, un programmeur en langage C utilise les
instructions
for (i = 0; i < 100; i++)pour sa ligne de code. L'utilisation d'un idiotisme par le programmeur lui évite d'avoir à remettre en question la structure détaillée du programme et améliore la qualité du produit5.
Description
Les patrons servent à documenter des bonnes pratiques basées sur l'expérience. Ils proposent des solutions à des problèmes qui peuvent être difficilement résolus par un seul composant : la description de la plupart des patrons implique plusieurs rôles qui peuvent être joués par plusieurs composants d'un logiciel. Par exemple, le patron Observer implique deux rôles qui sont le sujet et l'observateur6.Les patrons apportent un vocabulaire commun entre l'architecte informatique et le programmeur. Si le programmeur connaît le patron de conception observer, alors l'architecte informatique n'aura pas besoin de lui donner de longues explications et le dialogue se limitera à « ici, j'ai utilisé un Observer »6.
En programmation informatique, les patrons de conception peuvent être utilisés avant, pendant, ou après le travail de programmation : utilisé avant, le programmeur utilisera le patron comme guide lors de l'écriture du code source ; utilisé après, il servira comme exemple pour relier différents modules de code source déjà écrits, ce qui implique d'écrire le code source nécessaire à leur liaison, et le code qui les fera correspondre au patron de conception ; s'il est utilisé pendant le travail de programmation, le programmeur constatera que le code qui vient d'être écrit a des points communs avec un patron existant et effectuera les modifications nécessaires pour que le code corresponde au patron7. La bonne pratique consiste toutefois à n'utiliser un patron qu'une fois qu'il est clair que sa flexibilité est nécessaire8.
Histoire
Formalisés dans le livre du « Gang of Four » (GoF, Erich Gamma, Richard Helm, Ralph Johnson (en) et John Vlissides (en)) intitulé Design Patterns – Elements of Reusable Object-Oriented Software9 en 1995. Les patrons de conception tirent leur origine des travaux de l'architecte Christopher Alexander dans les années 70, dont son livre A Pattern Language définit un ensemble de patrons d'architecture.Citations
- « Chaque patron décrit un problème qui se manifeste constamment dans notre environnement, et donc décrit le cœur de la solution à ce problème, d’une façon telle que l’on puisse réutiliser cette solution des millions de fois, sans jamais le faire deux fois de la même manière » — Christopher Alexander, 1977.
- « Les patrons offrent la possibilité de capitaliser un savoir précieux né du savoir-faire d’experts » — Buschmann, 1996.
Formalisme
La description d'un patron de conception suit un formalisme fixe :- Nom ;
- Description du problème à résoudre ;
- Description de la solution : les éléments de la solution, avec leurs relations. La solution est appelée patron de conception ;
- Conséquences : résultats issus de la solution.
Un aspect de construction plus important est l'orthogonalité : chaque patron doit correspondre à une approche différente, qui ne répète pas les idées ou stratégies présentes dans d'autres patrons. Cette qualité permet au concepteur d'analyser un problème et d'en résoudre chaque aspect d'une façon organisée, ainsi que de combiner les patrons pour construire une solution. Certains auteurs voient un manque d'orthogonalité dans les patrons GoF, tandis que d'autres en proposent encore davantage (Vlissides, Grand).
Patrons de conception du GoF
Les patrons de conception ont été formellement reconnus en 1994 à la suite de la parution du livre Design Patterns: Elements of Reusable Software, co-écrit par quatre auteurs : Gamma, Helm, Johnson et Vlissides (Gang of Four - GoF ; en français la bande des quatre). Ce livre, devenu un best-seller, décrit vingt-trois « patrons GoF » et comment s'en servir10.Il existe trois familles de patrons de conception selon leur utilisation :
- de construction : ils définissent comment faire l'instanciation et la configuration des classes et des objets ;
- structuraux : ils définissent comment organiser les classes d'un programme dans une structure plus large (séparant l'interface de l'implémentation) ;
- comportementaux : ils définissent comment organiser les objets pour que ceux-ci collaborent (distribution des responsabilités) et expliquent le fonctionnement des algorithmes impliqués.
- Factory et abstract factory
- Ce patron fournit une interface pour créer des familles d'objets sans spécifier la classe concrète11. Le patron factory (en français fabrique) est un patron récurrent. Une fabrique simple retourne une instance d'une classe parmi plusieurs possibles, en fonction des paramètres qui ont été fournis. Toutes les classes ont un lien de parenté, et des méthodes communes, et chacune est optimisée en fonction d'une certaine donnée10. Le patron abstract factory (en français fabrique abstraite) va un pas plus loin que la fabrique simple. Une fabrique abstraite est utilisée pour obtenir un jeu d'objets connexes. Par exemple pour implémenter une charte graphique : il existe une fabrique qui retourne des objets (boutons, menus) dans le style de Windows, une qui retourne des objets dans le style de Motif, et une dans le style de Macintosh. Une fabrique abstraite est obtenue en utilisant une fabrique simple10.
- Adapter
- Ce patron convertit l'interface d'une classe en une autre interface exploitée par une application. Permet d'interconnecter des classes qui sans cela seraient incompatibles11. Il est utilisé dans le cas où un programme se sert d'une bibliothèque de classe, et que, à la suite d'une mise à jour de la bibliothèque, cette dernière ne correspond plus à l'utilisation qui en est faite, parce que son interface a changé. Un objet adapteur expose alors l'ancienne interface en utilisant les fonctionnalités de la nouvelle12.
- Bridge
- Ce patron permet de découpler une abstraction de son implémentation, de telle manière qu'ils peuvent évoluer indépendamment11. Il consiste à diviser une implémentation en deux parties : une classe d'abstraction qui définit le problème à résoudre, et une seconde classe qui fournit une implémentation. Il peut exister plusieurs implémentations pour le même problème et la classe d'abstraction comporte une référence à l'implémentation choisie, qui peut être changée selon les besoins13. Le patron bridge est fréquemment utilisé pour réaliser des récepteurs d'événements14.
- Builder
- Ce patron sépare le processus de construction d'un objet du résultat obtenu. Permet d'utiliser le même processus pour obtenir différents résultats11. C'est une alternative au pattern factory. Au lieu d'une méthode pour créer un objet, à laquelle est passée un ensemble de paramètres, la classe factory comporte une méthode pour créer un objet - le builder. Cet objet comporte des propriétés qui peuvent être modifiées et une méthode pour créer l'objet final en tenant compte de toutes les propriétés. Ce pattern est particulièrement utile quand il y a de nombreux paramètres de création, presque tous optionnels15.
- Chain of responsibility
- Ce patron vise à découpler l’émission d'une requête de la réception et le traitement de cette dernière en permettant à plusieurs objets de la traiter successivement11. Dans ce patron chaque objet comporte un lien vers l'objet suivant, qui est du même type. Plusieurs objets sont ainsi attachés et forment une chaîne. Lorsqu'une demande est faite au premier objet de la chaîne, celui-ci tente de la traiter, et s'il ne peut pas il fait appel à l'objet suivant, et ainsi de suite16.
- Command
- Ce patron emboîte une demande dans un objet, permettant de
paramétrer, mettre en file d'attente, journaliser et annuler des
demandes11. Dans ce patron un objet command correspond à une opération à effectuer. L'interface de cet objet comporte une méthode
execute. Pour chaque opération, l'application va créer un objet différent qui implémente cette interface - qui comporte une méthodeexecute. L'opération est lancée lorsque la méthodeexecuteest utilisée. Ce patron est notamment utilisé pour les barres d'outils17. - Composite
- Ce patron permet de composer une hiérarchie d'objets, et de manipuler de la même manière un élément unique, une branche, ou l'ensemble de l'arbre11. Il permet en particulier de créer des objets complexes en reliant différents objets selon une structure en arbre. Ce patron impose que les différents objets aient une même interface, ce qui rend uniformes les manipulations de la structure. Par exemple dans un traitement de texte, les mots sont placés dans des paragraphes disposés dans des colonnes dans des pages ; pour manipuler l'ensemble, une classe composite implémente une interface. Cette interface est héritée par les objets qui représentent les textes, les paragraphes, les colonnes et les pages18.
- Decorator
- Ce patron permet d'attacher dynamiquement des responsabilités à un objet. Une alternative à l'héritage11. Ce patron est inspiré des poupées russes. Un objet peut être caché à l'intérieur d'un autre objet décorateur qui lui rajoutera des fonctionnalités, l'ensemble peut être décoré avec un autre objet qui lui ajoute des fonctionnalités et ainsi de suite. Cette technique nécessite que l'objet décoré et ses décorateurs implémentent la même interface, qui est typiquement définie par une classe abstraite19.
- Façade
- Ce patron fournit une interface unifiée sur un ensemble d'interfaces d'un système11. Il est utilisé pour réaliser des interfaces de programmation. Si un sous-système comporte plusieurs composants qui doivent être utilisés dans un ordre précis, une classe façade sera mise à disposition, et permettra de contrôler l'ordre des opérations et de cacher les détails techniques des sous-systèmes20.
- Factory method
- Ce patron fournit une interface pour créer un objet qui laisse la possibilité aux sous-classes de décider quel type d'objet créer11. Ce patron est utilisé lorsque la classe d'un objet n'est pas connue au moment de la compilation. Une méthode pour créer un objet factory method est définie dans une classe abstraite, et implémentée dans les différentes sous-classes. La factory method peut également comporter une implémentation par défaut16.
- Flyweight
- Dans le patron flyweight (en français poids-mouche), un type d'objet est utilisé pour représenter une gamme de petits objets tous différents11. Ce patron permet de créer un ensemble d'objets et de les réutiliser. Il peut être utilisé par exemple pour représenter un jeu de caractères : Un objet factory va retourner un objet correspondant au caractère recherché. La même instance peut être retournée à chaque fois que le caractère est utilisé dans un texte20.
- Interpreter
- Le patron comporte deux composants centraux : le contexte et l'expression20 ainsi que des objets qui sont des représentations d'éléments de grammaire d'un langage de programmation11. Le patron est utilisé pour transformer une expression écrite dans un certain langage de programmation - un texte source - en quelque chose de manipulable par programmation20 : Le code source est écrit conformément à une ou plusieurs règles de grammaire, et un objet est créé pour chaque utilisation d'une règle de grammaire. L'objet interpreter est responsable de transformer le texte source en objets21.
- Iterator
- Ce patron permet d'accéder séquentiellement aux éléments d'un
ensemble sans connaitre les détails techniques du fonctionnement de
l'ensemble11.
C'est un des patrons les plus simples et les plus fréquents. Selon la
spécification originale, il consiste en une interface qui fournit les
méthodes
NextetCurrent. L'interface en Java comporte généralement une méthodenextElementet une méthodehasMoreElements10. - Mediator
- Dans ce patron il y a un objet qui définit comment plusieurs objets communiquent entre eux en évitant à chacun de faire référence à ses interlocuteurs11. Ce patron est utilisé quand il y a un nombre non négligeable de composants et de relations entre les composants. Par exemple dans un réseau de 5 composants il peut y avoir jusqu'à 20 relations (chaque composant vers 4 autres). Un composant médiateur est placé au milieu du réseau et le nombre de relations est diminué : chaque composant est relié uniquement au médiateur22. Le mediator joue un rôle similaire à un sujet dans le patron observer et sert d'intermédiaire pour assurer les communications entre les objets23.
- Memento
- Ce patron vise à externaliser l'état interne d'un objet sans perte d'encapsulation. Permet de remettre l'objet dans l'état où il était auparavant11. Ce patron permet de stocker l'état interne d'un objet sans que cet état ne soit rendu public par une interface. Il est composé de trois classes : l´origine - d'où l'état provient, le memento - l'état de l'objet d'origine, et le gardien qui est l'objet qui manipulera le memento. L´origine comporte une méthode pour manipuler les memento. Le gardien est responsable de stocker les memento et de les renvoyer à leur origine. Ce patron ne définit pas d'interface précise pour les différent objets, qui sont cependant toujours au nombre de trois24.
- Observer
- Ce patron établit une relation un à plusieurs entre des objets, où
lorsqu'un objet change, plusieurs autres objets sont avisés du
changement11. Dans ce patron, un objet le sujet tient une liste des objets dépendants les observateurs qui seront avertis des modifications apportées au sujet.
Quand une modification est apportée, le sujet émet un message aux
différents observateurs. Le message peut contenir une description
détaillée du changement23. Dans ce patron, un objet observer comporte une méthode pour inscrire des observateurs. Chaque observateur comporte une méthode
Notify. Lorsqu'un message est émis, l'objet appelle la méthodeNotifyde chaque observateur inscrit25. - Prototype
- Ce patron permet de définir le genre d'objet à créer en dupliquant une instance qui sert d'exemple - le prototype11.
L'objectif de ce patron est d'économiser le temps nécessaire pour
instancier des objets. Selon ce patron, une application comporte une
instance d'un objet, qui sert de prototype. Cet objet comporte une méthode
clonepour créer des duplicata. Des langages de programmation comme PHP ont une méthodecloneincorporée dans tous les objets26. - Proxy
- Ce patron est un substitut d'un objet, qui permet de contrôler l'utilisation de ce dernier11. Un proxy est un objet destiné à protéger un autre objet. Le proxy a la même interface que l'objet à protéger. Un proxy peut être créé par exemple pour permettre d’accéder à distance à un objet (via un middleware). Il peut également être créé dans le but de retarder la création de l'objet protégé - qui sera créé immédiatement avant d'être utilisé. Dans sa forme la plus simple, un proxy ne protège rien du tout et transmet tous les appels de méthode à l'objet cible14.
- Singleton
- Ce patron vise à assurer qu'il n'y a toujours qu'une seule instance d'une classe en fournissant une interface pour la manipuler11. C'est un des patrons les plus simples. L'objet qui ne doit exister qu'en une seule instance comporte une méthode pour obtenir cette unique instance et un mécanisme pour empêcher la création d'autres instances16.
- State
- Ce patron permet à un objet de modifier son comportement lorsque son état interne change11. Ce patron est souvent utilisé pour implémenter une machine à états. Un exemple d'appareil à états est le lecteur audio - dont les états sont lecture, enregistrement, pause et arrêt. Selon ce patron il existe une classe machine à état, et une classe pour chaque état. Lorsqu'un événement provoque le changement d'état, la classe machine à état se relie à un autre état et modifie ainsi son comportement27.
- Strategy
- Dans ce patron, une famille d'algorithmes est encapsulée de manière à ce qu'ils soient interchangeables. Les algorithmes peuvent changer indépendamment de l'application qui s'en sert11. Il comporte trois rôles : le contexte, la stratégie et les implémentations. La stratégie est l'interface commune aux différentes implémentations - typiquement une classe abstraite. Le contexte est l'objet qui va associer un algorithme avec un processus20.
- Template method
- Ce patron définit la structure générale d'un algorithme en déléguant certains passages. Permettant à des sous-classes de modifier l'algorithme en conservant sa structure générale11. C'est un des patrons les plus simples et les plus couramment utilisés en programmation orientée objet. Il est utilisé lorsqu'il y a plusieurs implémentations possibles d'un calcul. Une classe d'exemple (anglais template) comporte des méthodes d'exemple, qui, utilisées ensemble, implémentent un algorithme par défaut. Certaines méthodes peuvent être vides ou abstraites. Les sous-classes de la classe template peuvent remplacer certaines méthodes et ainsi créer un algorithme dérivé21.
- Visitor
- Ce patron représente une opération à effectuer sur un ensemble d'objets. Permet de modifier l'opération sans changer l'objet concerné ni la structure11. Selon ce patron, les objets à modifier sont passés en paramètre à une classe tierce qui effectuera des modifications. Une classe abstraite Visitor définit l'interface de la classe tierce. Ce patron est utilisé notamment pour manipuler un jeu d'objets, où les objets peuvent avoir différentes interfaces, qui ne peuvent pas être modifiés20.
- Modèle-vue-contrôleur
- Combinaison des patrons observateur, stratégie et composite, ce qui forme ainsi un patron d'architecture.
Patrons GRASP
Les patrons GRASP (general responsibility assignment software patterns (ou principles)), GRASP - sont des patrons créés par Craig Larman qui décrivent des règles pour affecter les responsabilités aux classes d'un programme orienté objet pendant la conception, en liaison avec la méthode de conception BCE (pour boundary control entity - en français MVC « modèle vue contrôleur »)28 :- Expert
- Créateur
- Faible couplage
- Forte cohésion
- Contrôleur
- Polymorphisme
- Indirection
- Fabrication pure
- Protection des variations
No comments:
Post a Comment