LES MODÈLES DE CONCEPTION : ÉLÉMENTS D’UN LOGICIEL ORIENTÉ OBJET RÉUTILISABLE

Chapitre 1 : Introduction

La conception d’un logiciel orienté objet est complexe, et celle d’un logiciel orienté objet réutilisable l’est encore plus. Vous devez trouver les objets pertinents, les répartir dans des classes à la bonne granularité, définir des interfaces de classe et des hiérarchies d’héritage, et établir des relations clés entre eux. Votre conception doit être spécifique au problème et suffisamment générale pour répondre aux questions et exigences futures.

Qu’est-ce qu’un modèle de conception ?

Un modèle de conception nomme, abstrait et identifie les aspects critiques d’une structure de conception standard qui l’aident à créer une conception orientée objet réutilisable. Le modèle de conception identifie les classes et instances participantes, leurs rôles et collaborations, ainsi que la répartition des responsabilités. Les modèles de conception décrivent des problèmes dans votre environnement et expliquent l’essentiel de la solution à ce problème afin que vous puissiez utiliser cette solution de manière itérative. Un modèle de conception comporte quatre éléments essentiels ;

  1. Le nom du modèle est un moyen de décrire un problème de conception, ses solutions et ses conséquences en un mot ou deux. Le fait de nommer un modèle vous permet de concevoir à un niveau d’abstraction plus élevé.
  2. Le problème : il s’agit d’expliquer quand mettre en œuvre le modèle. Il explique la situation et son contexte. Il décrit des problèmes de conception spécifiques, comme la manière de représenter les algorithmes en tant qu’objets.
  3. La solution : elle illustre les éléments qui composent la conception, leurs relations, leurs collaborations et leurs responsabilités.
  4. Les conséquences : il s’agit des résultats et des compromis résultant de l’application du modèle.

Modèles de conception en Smalltalk MVC

La triade de classes Modèle/Vue/Contrôleur (MVC) [KP88] est utilisée pour construire des interfaces utilisateur dans Smalltalk-80. Le modèle, la vue et le contrôleur comportent trois types d’objets. Le modèle est l’objet de l’application, la vue est sa présentation à l’écran et le contrôleur définit la manière dont l’interface utilisateur réagit aux entrées de l’utilisateur. Avant le MVC, les conceptions d’interface utilisateur avaient tendance à regrouper ces objets. Le MVC les a ensuite dissociés pour améliorer la flexibilité et la réutilisation. Le MVC découple les vues et les modèles en établissant un protocole de souscription/notification. Une vue doit s’assurer que son apparence reflète l’état du modèle. Chaque fois que les données du modèle changent, elles en informent les vues qui en dépendent. En réponse, chaque vue a la possibilité de se mettre à jour. Cette approche vous permet d’attacher plusieurs vues à un modèle afin de fournir différentes présentations. Vous pouvez également créer de nouvelles vues pour un modèle sans le réécrire.

MVC vous permet de modifier la façon dont une vue réagit à l’entrée de l’utilisateur sans modifier sa présentation visuelle. Vous pouvez, par exemple, modifier la façon dont elle réagit au clavier ou utiliser un menu contextuel à la place des touches de commande. MVC encapsule le mécanisme de réponse dans un objet contrôleur. Une hiérarchie de classes de contrôleurs facilite la création d’un nouveau contrôleur en tant que variation d’un contrôleur existant.

Description des modèles de conception

Les modèles de conception sont définis selon un format cohérent. Chaque modèle est divisé en sections selon le modèle suivant. Le modèle confère une structure uniforme à l’information, ce qui facilite l’apprentissage, la comparaison et l’utilisation des modèles de conception.

  • Nom du motif et classification : Le nom exprime succinctement l’essence du motif. Une bonne réputation est essentielle car elle fera partie de votre vocabulaire de conception. La classification du modèle reflète le schéma que nous présentons à la section 1.5.
  • L’intention : Une brève déclaration qui répond aux questions suivantes : Que fait le modèle de conception ? Quelle est sa raison d’être et quel est son objectif ? Quelle question ou quel problème de conception particulier aborde-t-il ?
  • Également connu sous d’autres noms connus pour le motif, le cas échéant.
  • Motivation : Un scénario qui illustre un problème de conception et la façon dont les structures de classes et d’objets du modèle résolvent le problème. Le système vous aidera à comprendre la description plus abstraite du modèle suivant.
  • Applicabilité : Quelles sont les situations dans lesquelles le modèle de conception peut être appliqué ? Quels sont les exemples de mauvaises conceptions auxquelles le modèle peut remédier ? Comment pouvez-vous reconnaître ces situations ?
  • Structure : Une représentation graphique des classes du modèle à l’aide d’une notation basée sur la technique de modélisation d’objets (OMT) [RBP+91]. Nous utilisons également des diagrammes d’interaction [JCJO92, Boo94] pour illustrer les séquences de requêtes et les collaborations entre les objets. L’annexe B décrit ces notations en détail.
  • Participants : Les classes et/ou objets participant au modèle de conception et leurs responsabilités.
  • Collaborations : Comment les participants collaborent pour assumer leurs responsabilités.
  • Conséquences : Comment le modèle soutient-il ses objectifs ? Quels sont les compromis et les résultats de l’utilisation du modèle ? Quel aspect de la structure du système vous permet-il de varier indépendamment ?
  • Mise en œuvre : Quels sont les pièges, les conseils ou les techniques à connaître lors de la mise en œuvre du modèle ? Existe-t-il des problèmes spécifiques au langage ?
  • Exemple de code : Fragments illustrant la manière dont vous pourriez mettre en œuvre le modèle en C++ ou en Smalltalk.
  • Utilisations connues : Exemples de motifs trouvés dans des systèmes réels. Nous incluons au moins deux exemples provenant de domaines différents.
  • Modèles apparentés : Quels sont les modèles de conception étroitement associés à celui-ci ? Quelles sont les différences essentielles ? Quels autres modèles devraient être utilisés ?

Comment les patrons de conception résolvent les problèmes de conception

Les modèles de conception résolvent les problèmes de conception en trouvant les objets appropriés ; les modèles de conception vous aident à identifier les abstractions les moins évidentes et les objets qui peuvent les capturer. Les modèles de conception déterminent également la granularité des objets ; les modèles de conception décrivent comment représenter des sous-systèmes complets en tant qu’objets et prendre en charge un grand nombre d’objets aux granularités les plus fines. Les modèles de conception vous aident à définir les interfaces en identifiant leurs éléments essentiels et les types de données envoyées à travers une interface. Un modèle de conception peut également vous indiquer ce qu’il ne faut pas mettre dans l’interface.

Citation préférée du chapitre : « Les patrons de classes créationnelles reportent une partie de la création de l’objet sur les sous-classes, tandis que les patrons d’objets créationnels la reportent sur un autre objet. Les modèles de classes structurels utilisent l’héritage pour composer des classes, tandis que les modèles d’objets structurels décrivent des façons d’assembler des objets. Les modèles de classes comportementales utilisent l’héritage pour décrire les algorithmes et le flux de contrôle, tandis que les modèles d’objets comportementaux décrivent la manière dont un groupe d’objets coopère pour effectuer une tâche qu’aucun objet seul ne peut réaliser.

seul ».

Chapitre deux : Une étude de cas : Conception d’un éditeur de documents

Structure du document

Un document contient des éléments graphiques essentiels tels que des caractères, des lignes, des polygones et d’autres formes. Ces éléments représentent l’ensemble des informations contenues dans le document. Cependant, ces éléments ne sont pas considérés en termes graphiques, mais en termes de structure physique du document – lignes, colonnes, figures, tableaux et autres sous-structures. À leur tour, ces sous-structures ont leurs sous-structures, et ainsi de suite. L’interface utilisateur de Lexi doit permettre aux utilisateurs de manipuler directement ces sous-structures. Par exemple, un utilisateur doit pouvoir traiter un diagramme comme une unité plutôt que comme une collection de primitives graphiques individuelles. L’utilisateur doit pouvoir se référer à un tableau comme à un tout, et non comme à une masse informe de texte et de graphiques. Cela contribue à rendre l’interface simple et intuitive.

Formatage

Après avoir trouvé un moyen de représenter la structure physique du document, vous devez déterminer comment construire une structure physique particulière. Une structure qui correspond à un document correctement formaté. La représentation et le formatage sont distincts : la capacité à capturer la structure physique du document ne nous dit pas comment arriver à un système particulier. Cette responsabilité incombe principalement à Lexi.

Encapsuler l’algorithme de formatage : Avec toutes ses contraintes et ses détails, le processus de formatage n’est pas facile à automatiser. Il existe de nombreuses approches au problème, et les gens ont développé divers algorithmes de formatage avec des forces et des faiblesses différentes. Lexi étant un éditeur de type « What You See Is What You Get », un compromis nécessaire à prendre en compte est l’équilibre entre la qualité et la vitesse du formatage. Comme les algorithmes de formatage ont tendance à être complexes, il est souhaitable qu’ils soient bien contenus ou, mieux encore, qu’ils soient complètement indépendants de la structure du document. Idéalement, nous pourrions ajouter un nouveau type de sous-classe Glyph sans tenir compte de l’algorithme de formatage. Inversement, l’ajout d’un nouvel algorithme de formatage ne devrait pas nécessiter la modification des glyphes existants.

Modèle de stratégie : L’encapsulation d’un algorithme dans un objet est l’objectif du modèle de stratégie. Les participants clés du modèle sont les objets Stratégie qui encapsulent différents algorithmes et le contexte dans lequel ils opèrent. Les compositeurs sont des stratégies ; ils encapsulent différents algorithmes de formatage. La composition est le contexte d’une stratégie de compositeur. La clé de l’application du modèle de stratégie est la conception d’interfaces pour le système et son contexte qui sont suffisamment générales pour prendre en charge une gamme d’algorithmes.

Embellir l’interface utilisateur

Considérez deux embellissements dans l’interface utilisateur de Lexi. La première ajoute une bordure autour de la zone d’édition de texte pour délimiter la page de texte. Le second ajoute des barres de défilement qui permettent à l’utilisateur de visualiser différentes parties de la page. Pour faciliter l’ajout et la suppression de ces embellissements (en particulier lors de l’exécution), vous ne devez pas utiliser l’héritage pour les ajouter à l’interface utilisateur. Vous obtiendrez une plus grande flexibilité si les autres objets de l’interface utilisateur ne savent même pas que les embellissements sont là. Cela nous permettra d’ajouter et de supprimer les embellissements sans modifier d’autres classes.

Du point de vue de la programmation, l’embellissement de l’interface utilisateur implique l’extension du code existant. L’utilisation de l’héritage pour réaliser cette extension empêche de réorganiser les embellissements au moment de l’exécution, mais un problème tout aussi grave est l’explosion des classes résultant d’une approche basée sur l’héritage.

Modèle de décorateur : Le modèle du décorateur (196) capture les relations entre les classes et les objets qui supportent l’embellissement par l’enfermement transparent. Le terme « embellissement » a une signification plus large que celle que nous avons envisagée ici. Dans le modèle Decorator, l’embellissement fait référence à tout ce qui ajoute des responsabilités à un objet.

Citation préférée : « Le choix de la représentation interne du document influe sur presque tous les aspects de la conception de Lexi.

Chapitre trois : Modèles de création

Les modèles de conception créative font abstraction du processus d’instanciation. Ils contribuent à rendre un système indépendant de la manière dont ses objets sont créés, composés et représentés. Un modèle de création de classe utilise l’héritage pour varier la classe instanciée, tandis qu’un modèle de création d’objet délègue l’instanciation à un autre objet.

Les modèles de création deviennent essentiels lorsque les systèmes dépendent davantage de la composition d’objets que de l’héritage de classes. Dans ce cas, l’accent n’est plus mis sur le codage en dur d’un ensemble fixe de comportements, mais sur la définition d’un groupe plus restreint de comportements fondamentaux qui peuvent être composés d’autres comportements plus complexes. Ainsi, la création d’objets ayant des comportements spécifiques nécessite plus que la simple instanciation d’une classe.

Il y a deux thèmes récurrents dans ces modèles. Premièrement, ils encapsulent tous des connaissances sur les classes concrètes utilisées par le système. Deuxièmement, ils cachent la manière dont les instances de ces classes sont créées et assemblées. Tout ce que le système dans son ensemble connaît des objets, ce sont leurs interfaces définies par des classes abstraites. Les modèles créatifs peuvent parfois être des concurrents. En d’autres termes, il existe des cas où Prototype ou Abstract Factory peuvent être utilisés avec profit. Dans d’autres cas, ils sont complémentaires : Le constructeur peut utiliser l’un des différents modèles pour mettre en œuvre les composants à construire. Le prototype peut utiliser Singleton dans son implémentation. Les modèles créatifs sont les suivants ;

Usine abstraite : Fournir une interface pour créer des familles d’objets liés ou dépendants sans spécifier leurs classes concrètes.

Constructeur : Séparer la construction d’un objet complexe de sa représentation afin que le même processus de construction puisse créer des expressions différentes.

Méthode d’usine : Définir une interface pour la création d’un objet, mais laisser les sous-classes décider de la classe à instancier. La méthode Factory permet à une classe de différer l’instanciation à des sous-classes.

Prototype : Spécifiez les types d’objets à créer à l’aide d’une instance prototypique et créez de nouveaux objets en copiant ce prototype.

Singleton : Assurez-vous qu’une classe n’a qu’une seule instance et fournissez un point d’accès global à cette instance.

Citation préférée du chapitre : « Il y a deux thèmes récurrents dans ces modèles. Premièrement, ils encapsulent tous des connaissances sur les classes concrètes utilisées par le système. Deuxièmement, ils cachent la façon dont les instances de ces classes sont créées et assemblées. »

Chapitre quatre : Modèles structurels

Les modèles structurels traitent de la manière dont les classes et les objets sont composés pour former des structures plus importantes. Les modèles structurels de classes utilisent l’héritage pour rassembler les interfaces ou les implémentations. A titre d’exemple simple, considérez comment

les successions multiples mélangent deux ou plusieurs classes en une seule. Le résultat est une classe qui combine les propriétés de ses classes mères. Ce modèle est pratique pour faire fonctionner ensemble des bibliothèques de classes développées indépendamment les unes des autres. Un autre exemple est la forme de classe du modèle de l’adaptateur. En général, un adaptateur rend une interface conforme à une autre, fournissant une abstraction uniforme de différentes interfaces. Un adaptateur de classe accomplit cette tâche en héritant de manière privée d’une classe d’adaptateur. L’adaptateur exprime ensuite son interface en termes d’adaptateurs. Les modèles d’objets structurels décrivent des façons de composer des objets pour réaliser de nouvelles fonctionnalités. La flexibilité accrue de la composition d’objets provient de la possibilité de modifier le document au moment de l’exécution, ce qui est impossible avec la composition de classes statiques. Un modèle d’objet structurel décrit la construction d’une hiérarchie de classes pour deux types d’objets : les objets primitifs et les objets composites. Les objets composites vous permettent de composer des objets primitifs et d’autres objets composites dans des structures arbitrairement complexes. Vous trouverez ci-dessous les modèles structurels que vous devez connaître ;

Adaptateur : Convertir l’interface d’une classe en une autre interface attendue par les clients. L’adaptateur permet à des classes de travailler ensemble alors qu’elles ne pourraient le faire autrement en raison d’interfaces incompatibles.

Pont : Découpler une abstraction de sa mise en œuvre afin que les deux puissent varier indépendamment.

Composé : Composez des objets dans des structures arborescentes pour représenter des hiérarchies partie-tout. Le composite permet aux clients de traiter uniformément les objets individuels et les compositions d’objets.

Décorateur : Attachez dynamiquement des responsabilités supplémentaires à un objet. Les décorateurs constituent une alternative flexible à la sous-classe pour étendre les fonctionnalités.

Facade : Fournir une interface unifiée à un ensemble d’interfaces dans un sous-système. Une façade définit une interface de niveau supérieur qui facilite l’utilisation du sous-système.

Poids plume : Utilisez le partage pour prendre en charge efficacement un grand nombre d’objets à grain fin.

Proxy : Fournir un substitut ou une place pour un autre objet afin d’en contrôler l’accès.

Citation préférée : « Plutôt que de composer des interfaces ou des implémentations, les modèles d’objets structurels décrivent des façons de composer des objets pour réaliser de nouvelles fonctionnalités . »

Chapitre cinq : Modèles de comportement

Les modèles comportementaux concernent les algorithmes et l’attribution des responsabilités entre les objets.

Les modèles comportementaux décrivent non seulement les modèles d’objets ou de classes, mais aussi les modèles de communication entre eux. Ces modèles caractérisent un flux de contrôle complexe qui est difficile à suivre au moment de l’exécution. Ils vous détournent du flux de contrôle pour vous permettre de vous concentrer sur la manière dont les objets sont interconnectés. Les modèles de classes comportementales utilisent l’héritage pour distribuer le comportement entre les classes. Ce chapitre comprend deux de ces modèles. Le modèle de méthode (360) est le plus simple et le plus courant des deux. Une méthode modèle est une définition abstraite d’un algorithme. Elle définit l’algorithme étape par étape. Chaque étape invoque soit une opération abstraite, soit une opération primitive. Une sous-classe complète l’algorithme en définissant les opérations abstraites. L’autre modèle de classe comportementale est Interprète (274), qui représente la grammaire comme une hiérarchie de classes et implémente un interprète comme une opération sur les instances de ces classes. Les modèles d’objets comportementaux utilisent la composition d’objets plutôt que l’héritage. Certains décrivent la manière dont un groupe d’objets pairs coopère pour effectuer une tâche qu’aucun objet ne peut réaliser seul. Il est important de savoir comment les objets pairs se connaissent les uns les autres. Les pairs peuvent maintenir des références explicites les uns aux autres, ce qui accroît leur couplage. À l’extrême, chaque objet connaîtrait tous les autres. Le modèle du médiateur (305) évite ce problème en introduisant un objet médiateur entre les pairs. Le médiateur fournit l’indirection nécessaire à un couplage lâche. Il s’agit là de quelques-uns des modèles de comportement ;

Interprète : Étant donné une langue, définissez une représentation de sa grammaire et un interprète qui utilise la représentation pour interpréter les phrases de la langue.

Commande : Encapsule une requête sous forme d’objet, ce qui vous permet de paramétrer les clients avec différentes requêtes, de mettre les requêtes en file d’attente ou de les enregistrer, et de prendre en charge les opérations annulables.

Itérateur : Fournir un moyen d’accéder aux éléments d’un objet agrégé de manière séquentielle sans exposer sa représentation sous-jacente.

Médiateur : Définir un objet qui encapsule la manière dont un ensemble d’objets interagissent. Le médiateur favorise le couplage lâche en empêchant les objets de se référer explicitement les uns aux autres et en vous permettant de faire varier leur interaction de manière indépendante.

Mémento : Sans violer l’encapsulation, capturez et externalisez l’état interne d’un objet de manière à ce que l’objet puisse être restauré dans cet état ultérieurement.

Observer : Définissez une dépendance de type « un pour plusieurs » entre les objets, de sorte que lorsqu’un objet change d’état, tous ses dépendants en sont informés et mis à jour automatiquement.

État : Permet à un objet de modifier son comportement lorsque son état interne change. L’objet semblera changer de classe.

Stratégie : Définir une famille d’algorithmes, encapsuler chacun d’entre eux et les rendre interchangeables. La stratégie permet à l’algorithme de varier indépendamment des clients qui l’utilisent.

Coup de cœur du chapitre : Une question importante ici est de savoir comment les objets pairs se connaissent les uns les autres ».

COMMENT CE LIVRE PEUT AIDER LES DÉVELOPPEURS DE LOGICIELS

Le livre « Design Patterns : Elements of Reusable Object-Oriented Software » par Erich Gamma, Richard Helm, Ralph Johnson et John Vlissides est un ouvrage de référence dans le domaine du génie logiciel qui décrit 23 modèles de conception pour la programmation orientée objet. C’est un livre qui peut aider les développeurs de logiciels en leur fournissant des solutions réutilisables à des problèmes de conception courants dans le développement de logiciels orientés objet. Ces modèles résolvent des problèmes de conception courants et favorisent un code flexible, réutilisable et facile à maintenir. En comprenant et en appliquant ces modèles, les développeurs de logiciels peuvent écrire un code plus efficace, modulaire et extensible qui est plus facile à comprendre, à modifier et à maintenir au fil du temps.

DevologyX OÜ
Harju maakond, Tallinn, Lasnamäe
linnaosa,
Vaike-Paala tn 1, 11415

+372 6359999
[email protected]
DevologyX Limited
Nakawa Business Park
Kampala
Uganda

+256206300922
[email protected]

DevologyX Pty Ltd
Tijger Park 3
Willie van Schoor Drive
Bellville
Cape Town
7530

[email protected]

DevologyX OÜ
Harju maakond, Tallinn, Lasnamäe
linnaosa,
Vaike-Paala tn 1, 11415

+372 6359999
[email protected]
DevologyX Limited
Nakawa Business Park
Kampala
Uganda

+256206300922
[email protected]

DevologyX Pty Ltd
TijgerPark 3
Willie van Schoor Drive
Bellville
Cape Town
7530

[email protected]