Design patterns in Java

Les 10 types de modèles de conception les plus populaires en Java

/ 11.01.2024 Java

Dans le développement de logiciels, il est essentiel d’assurer la flexibilité de la conception de manière à ce qu’elle soit facile à maintenir, efficace et qu’elle puisse s’adapter à l’évolution des conditions technologiques ou commerciales. Par conséquent, pour que le code de notre application réponde à ces conditions, nous devons utiliser des pratiques éprouvées, dont les modèles de conception.  

Java, l’un des langages de programmation les plus populaires, possède son propre ensemble de modèles de conception de logiciels que tout programmeur Java devrait connaitre. Dans cet article, nous allons découvrir les plus populaires d’entre eux et analyser leur utilisation. 

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

Un modèle de conception est une solution réutilisable à un problème typique rencontré dans la conception de logiciels et qui peut être appliquée à diverses situations. Il ne s’agit pas de conceptions ou de codes finis, mais de pratiques éprouvées par de nombreux développeurs de logiciels, avec des solutions réutilisables prêtes à l’emploi pour certains problèmes rencontrés dans la conception de solutions orientées objet

Un rôle clé dans le processus de popularisation du concept des patrons de conception a été joué par les auteurs du bestseller « Design Patterns: Elements of Reusable Object-Oriented Software » : Erich Gamma, Richard Helm, Ralph Johnson et John Vlissides, collectivement connus sous le nom de « Gang of Four » (GoF).  

Depuis 1994, des dizaines d’autres modèles ont été découverts pour la programmation orientée objet. L’« approche par motifs » est devenue très populaire dans de nombreux cadres de travail. Par conséquent, il existe aujourd’hui beaucoup plus de modèles en dehors de la conception orientée objet. Aujourd’hui, les développeurs de logiciels utilisent ces modèles, parfois même inconsciemment. D’un autre côté, il est logique de les utiliser intentionnellement pour parler aux programmeurs qui utilisent les mêmes éléments de langage et partagent le même code source.  

Pourquoi les modèles de conception Java sont-ils importants ?   

Les modèles de conception Java ont gagné en popularité pour plusieurs raisons. Tout d’abord, ils favorisent les logiciels orientés objet réutilisables, permettant aux développeurs d’écrire un code modulaire et extensible. Cela facilite la maintenance et la mise à jour des systèmes logiciels à long terme.   

Le modèle de l’usine, par exemple, est un modèle de conception logicielle qui fournit une interface pour la création d’objets, mais qui permet aux sous-classes de décider de la classe dont elles doivent créer une instance. Cela favorise la réutilisation du code en permettant aux développeurs de créer des objets sans spécifier la classe exacte de l’objet qui sera créé.   

Deuxièmement, les modèles de conception améliorent la lisibilité et la maintenabilité du code. En suivant une structure standard, les modèles rendent le code existant plus facile à comprendre, ce qui est particulièrement utile lorsque l’on travaille en équipe ou que l’on revient à la base du code après une longue période.   

Trois catégories de modèles de conception couramment utilisés 

Les modèles les plus universels et de hauts niveaux sont ceux que nous allons aborder aujourd’hui : les modèles architecturaux. Les développeurs peuvent les appliquer à pratiquement n’importe quel langage de programmation et ils les utilisent pour concevoir l’architecture d’une application entière. 

Selon le manuel susmentionné, 23 modèles de conception peuvent être divisés en trois catégories en fonction de la responsabilité exercée : les modèles créatifs, structurels et comportementaux. Examinons maintenant de plus près quelques-uns des principaux modèles de conception utilisés en Java. 

Modèles de conception créative 

Ces modèles de conception traitent de la manière de créer des classes, des méthodes et des types de données, en se concentrant sur le processus de création d’objets et en essayant de composer des objets d’une manière appropriée à la situation. Les modèles de création visent à rendre la création d’objets plus souple et à la séparer du code client, ce qui favorise la réutilisation et la maintenance du code.    

  • Factory 

Le modèle Factory fournit une interface pour la création d’objets dans une superclasse, mais permet aux sous-classes de modifier les types d’objets qui seront créés. Il est utilisé lorsqu’un système doit être indépendant de la création, de la composition et de la représentation des objets. Cela permet à une classe de déléguer la responsabilité de la création d’instances à ses sous-classes.   

Ce modèle de création est couramment utilisé dans les scénarios où plusieurs classes implémentent une interface commune ou étendent une classe de base commune. Il existe différentes variantes des modèles de création de classe, telles que Simple Factory, Factory Method et Abstract Factory. Chaque variante a ses avantages et ses cas d’utilisation, ce qui vous permet de choisir celle qui convient le mieux à vos besoins spécifiques. 

  • Constructeur 

Le schéma de construction est un schéma de conception créative qui sépare la construction d’un objet complexe de sa représentation, permettant au même processus de construction de créer différentes représentations. Il comprend une classe de directeur, qui coordonne le processus de construction, et une interface de constructeur avec des classes spécifiques mettant en œuvre les étapes de la construction. 

 Builder est souvent utilisé par les développeurs à l’aide de la bibliothèque Lombok, qui génère du code Java pour nous et, entre autres, permet également la création de méthodes utilisées dans Builder. Ainsi, en créant des classes et de nouveaux objets, nous pouvons l’utiliser sans effort, sans écrire beaucoup de code. Il est utilisé lorsqu’un objet doit être construit avec de nombreuses configurations possibles ou lorsque le processus de construction comporte de nombreuses étapes. 

  • Singleton 

Le modèle de conception Singleton garantit qu’une classe n’a qu’une seule instance, qui est également le point d’accès global à cette instance. Il est extrêmement utile lorsqu’il s’agit d’implémentations de services que nous n’utilisons qu’une seule fois dans l’ensemble du programme, quel que soit l’endroit où elles sont créées. Le modèle du singleton est une solution particulièrement utilisée pour les connexions à la base de données ou aux appareils qui utilisent la communication par port série. En n’ayant qu’une seule instance de la classe, vous pouvez garantir une utilisation efficace des ressources et éviter les charges inutiles. 

  • Prototype 

 Le modèle du prototype est généralement utilisé lorsque nous disposons d’une instance d’une classe (prototype) et que nous souhaitons créer de nouveaux objets en copiant simplement le prototype. Ce modèle est particulièrement utile lorsque la création d’un nouvel objet est plus couteuse ou plus compliquée que la copie d’un objet existant. Il est particulièrement utile dans les scénarios où la création d’objets doit être dynamique et flexible. 

Modèles structurels 

Les modèles de conception structurelle traitent des relations entre les objets apparentés pour former des structures plus larges. Ces modèles permettent de définir les relations entre les entités et de simplifier la conception de systèmes complexes. 

  • Décorateur 

Le modèle du décorateur permet d’ajouter un comportement à un objet unique, de manière statique ou dynamique, sans affecter le comportement des autres objets de la même classe. Il s’agit d’un modèle structurel impliquant un ensemble de classes de décorateurs utilisées pour envelopper des composants précis. Il est le plus souvent utilisé lorsque l’on souhaite étendre le comportement d’objets individuels, sans modifier leur code. 

  • Façade 

Le modèle Façade fournit une interface simplifiée (mais limitée) à un système complexe de classes, de bibliothèques ou de cadres, réduit la complexité globale de l’application et aide à déplacer les dépendances non désirées en un seul endroit. L’objectif principal du modèle de façade est de simplifier et de normaliser l’ensemble des interfaces, ce qui rend le sous-système plus accessible et plus facile à utiliser pour les clients. Les modèles de façade sont le plus souvent utilisés dans les applications écrites en Java, lorsque l’on travaille avec des bibliothèques et des API complexes. 

  • Proxy (procuration) 

Un modèle de conception de proxy est un représentant ou un proxy d’un autre objet pour obtenir un accès supervisé à l’objet qu’il représente. En utilisant ce modèle, nous pouvons minimiser la charge et augmenter les performances. Si nous devons utiliser une bibliothèque dont nous savons qu’elle entrainera une charge importante sur le serveur de l’unité centrale, nous pouvons, pour ainsi dire, reporter l’opération jusqu’au moment final où nous devrons l’utiliser. Dans le cas des applications, nous économisons la mémoire et les ressources matérielles pour les opérations de calcul lourdes et nous ne chargeons les éléments complexes que lorsqu’ils sont nécessaires. 

Modèles de comportement  

 Ils concernent le comportement des objets liés ou dépendants qui coopèrent et la manière dont les classes et les objets interagissent, communiquent et coopèrent. Les modèles comportementaux concernent principalement la délégation de responsabilité entre les objets existants et les modèles de communication entre eux. Ils sont très souvent utilisés dans les projets d’entreprise. 

En effet, en utilisant des bibliothèques tierces, nous pouvons être confrontés à des fuites de mémoire, qui peuvent nous causer des problèmes que nous ne découvrirons que dans quelques semaines ou quelques mois. Dans de telles situations, il est utile d’utiliser différents modèles de conception pour surveiller les performances de l’application, par exemple. 

  • Stratégie 

Le modèle de stratégie définit une famille d’algorithmes, encapsule chacun d’entre eux et leur permet de changer. Le modèle de stratégie permet à un algorithme de changer indépendamment des clients qui l’utilisent. Il permet au client de choisir parmi la famille d’algorithmes au moment de l’exécution. L’idée principale du modèle de stratégie est de séparer les algorithmes des clients qui les utilisent, ce qui favorise la flexibilité et l’extensibilité. 

  • Visiteur 

Le modèle du visiteur est chargé d’effectuer une opération précise sur une structure de données complexe. Il permet de définir une nouvelle opération sans modifier les classes d’éléments sur lesquelles elle s’effectue. Cela signifie, par exemple, qu’il enregistrera pour nous les heures de l’opération ou qu’il nous dira par qui, quand et comment certaines fonctions ont été exécutées.  

  • Observateur 

 Le modèle de conception de l’observateur définit une relation un-à-plusieurs entre les objets, de sorte que lorsqu’un objet change d’état, tous les objets qui en dépendent en sont automatiquement informés et mis à jour. D’une part, le modèle de l’observateur garantit que nous disposons d’un module qui nous publie des évènements, par exemple lorsqu’un utilisateur a demandé certaines données, et que nous créons ensuite un évènement qui, à son tour, déclenche une réaction dans l’autre partie du système, générant les données correspondantes. 

Trois exemples d’utilisation de modèles de conception dans le développement de logiciels 

Vous trouverez ici des exemples de code sur l’utilisation des modèles de conception dans le processus de développement de logiciels. 

Exemple n° 1 

Dans le premier cas, nous utiliserons quatre types de modèles de conception de logiciels pour résoudre le problème de la création de différents objets véhicules ayant des comportements spécifiques. 

  • Le modèle de conception Builder obtenu avec l’annotation @SuperBuilder est utilisé pour créer des méthodes Builder lors de l’héritage. Le modèle @Builder de Lombok ne s’applique pas ici. 
  • Le modèle de conception d’usine utilisé dans la classe VehicleFactory pour produire des types d’objets en fonction du nom. 
  • Les méthodes d’usine (méthodes de fabrication) définies avec les classes VehicleCreator contiennent des détails sur la fabrication de véhicules individuels. 
  • Le modèle de conception stratégique utilisé sous la forme d’EconomicDriving et d’AggressiveDriving définit les styles de conduite des différents véhicules. 

Un exemple d’utilisation de 4 modèles pour résoudre le problème de la création de différents objets Véhicule ayant un comportement spécifique.

Après avoir lancé le programme, vous verrez apparaitre l’écran : 

  • 24.0L V12 diesel truck economic driving 
  • 6.0L V6 diesel bus economic driving 
  • 2.0L R4 petrol car aggressive driving 

Exemple n° 2 

Dans le deuxième exemple, nous utiliserons le Memento comme modèle de conception comportementale (il permet de sauvegarder et de restaurer l’état précédent d’un objet sans révéler les détails de sa mise en œuvre) dans un programme tel que Paint pour obtenir la possibilité d’une fonction « Annuler » ou « Retour en arrière » à 10 niveaux. 

Nous pouvons dessiner des formes sur le canevas (Canvas) et le remplir de couleurs. Chaque fois que nous appuyons sur Save, Caretaker crée et enregistre l’état actuel du canevas sous la forme d’un objet CanvasMemento. Si nous appuyons sur Undo, nous revenons à l’état précédent. 

Après avoir exécuté le programme deux fois, enregistrez les modifications, modifiez-les une nouvelle fois, puis utilisez deux fois la fonction « undo » pour rétablir les valeurs précédentes du canevas. 

Memento design pattern as example of architectural pattern 

Sur l’écran, nous obtenons : 

  • Canvas after all operations: draw:Circle fill:Red draw:Triangle 
  • Canvas after undo draw triangle: draw:Circle fill:Red 
  • Canvas after undo fill red: draw:Circle 

Exemple n° 3 

Le troisième exemple est l’application du modèle de conception Visiteur à un inspecteur en bâtiment, qui est chargé d’effectuer des actions connues de lui seul lors de la visite des pièces successives d’une maison. 

Une fois l’inspecteur accepté et admis dans la maison (house.accept(inspector)), BuildingInspector commence à inspecter les pièces définies lors de la construction de la maison. Il effectue des actions spécifiques dans chaque pièce et vérifie finalement la structure de la maison entière lorsque nous appelons « visitor.visit(this) » dans la méthode d’acceptation de la classe House. 

Visitor pattern separates algorithms from the objects on which they operate-better object composition 

Sur l’écran, après l’achèvement du programme selon l’ordre des pièces lors de la création de la maison : 

  1. Inspecting the quality of kitchen appliances and safety. 
  2. Checking living room space and ventilation. 
  3. Inspecting plumbing and hygiene conditions in the bathroom. 
  4. Performing an overall structural integrity check of the house. 

Quels sont les éléments à prendre en compte lors du choix des modèles de conception ? 

Lors de la mise en œuvre des modèles de conception, il est important de ne pas trop compliquer notre projet. Il est préférable de commencer par des solutions simples, tandis que les modèles de conception sont introduits pour résoudre le problème de la complexité.   

Il est également important de respecter les normes de codage et les meilleures pratiques. Des styles de codage cohérents facilitent la compréhension et la maintenance du code par l’équipe, même en cas d’utilisation de modèles de conception.   

Pour guider les membres de l’équipe et les futurs réviseurs de code, il est nécessaire de documenter clairement les décisions de conception. Bien que les modèles de conception puissent faciliter la maintenance, une mauvaise mise en œuvre peut introduire des erreurs. Par conséquent, nous devrions toujours utiliser des tests complets pour garantir la mise en œuvre correcte de nos modèles de conception. 

Design patterns in code refactoring – comment les utiliser à bon escient ? 

Si le modèle de conception choisi n’apporte pas les avantages escomptés ou si les exigences changent, vous devez être prêt à remanier le code, car les modèles de conception doivent s’adapter à l’évolution des besoins du projet.   

  Lorsque l’on aborde le remaniement, il est certainement utile de comprendre l’ensemble du système d’ingénierie logicielle de manière holistique afin de pouvoir décider consciemment si l’on souhaite réécrire le système et à quelle échelle, par exemple, y a-t-il des problèmes de performance ? Le problème réside-t-il simplement dans le fait que, par exemple, nous aimerions utiliser une nouvelle version d’une bibliothèque dont l’interface est entièrement différente ?    

Si la décision est prise, par exemple, de réécrire le module en tenant compte de la structure actuelle, et si les modèles sont utilisés de manière réfléchie, cela vaut la peine de les utiliser. Ils permettent d’étendre et de développer le projet sans y consacrer trop de temps. 

D’un autre côté, l’introduction de patrons à partir de zéro dans un projet écrit de manière désordonnée et incompréhensible peut nous amener à commencer un nouveau projet à partir de zéro. C’est-à-dire que nous passons d’abord plusieurs mois à comprendre une ancienne version du projet, puis nous déterminons que parfois 3 ou 4 techniques de conception logicielle comme les patrons de conception pourraient résoudre les problèmes sous-jacents. Cela signifie que dès le début, lorsque nous créons la première étape du projet, le MVP avec les fonctions les plus importantes pour le client, nous utilisons plusieurs modèles et mettons en œuvre les modules suivants en fonction de ces modèles. 

Résumé    

Dans cet article, nous avons abordé quelques-uns des modèles de conception Java les plus populaires, tels que les modèles créatifs, structurels et comportementaux, et nous avons expliqué comment ils peuvent être appliqués à la programmation Java, mais il existe également de nombreux autres modèles. Mieux vous comprendrez et utiliserez ces modèles de conception de logiciels dans votre travail quotidien, plus vous pourrez améliorer la qualité de votre code Java, en faciliter la maintenance et devenir un programmeur plus compétent et plus efficace. 

Si vous souhaitez discuter avec des ingénieurs logiciels expérimentés de leurs pratiques en matière de codage, de migration ou de refonte, contactez-nous. Nous serons heureux de discuter de nos expériences et de vous conseiller des solutions efficaces pour votre projet. 

Catégorie: Java


Dominik Wilczyński
Dominik Wilczyński Senior Java Developer
Mariola Nowak Content Writer

Conception, développement, DevOps ou Cloud - de quelle équipe avez-vous besoin pour accélérer le travail sur vos projets ?

Discutez avec vos partenaires de consultation pour voir si nous sommes compatibles.

Jakub Orczyk

Membre du Conseil d’administration/Directeur des ventes VM.PL

Réservez une consultation gratuite
kuba (2)