Formation  ·  Gang of Four  ·  TypeScript

Design Patterns

23 plans éprouvés pour résoudre les problèmes de conception qui reviennent tout le temps. Non pas du code à copier-coller, mais un vocabulaire partagé et des solutions qui rendent vos systèmes plus souples, plus clairs, plus faciles à faire évoluer.

5
Créationnels
Comment créer des objets — en cachant le « comment » et le « quel type ».
7
Structurels
Comment assembler objets et classes en structures plus grandes.
11
Comportementaux
Comment les objets communiquent et se répartissent les responsabilités.
on commence par « c'est quoi, au juste ? »
Introduction

Avant de plonger

Un design pattern est une solution générale, nommée et réutilisable, à un problème de conception qui revient souvent. Ce n'est pas une librairie qu'on installe, ni un bout de code à copier : c'est un plan qu'on adapte à sa situation.

Pourquoi s'embêter avec ça ?

  • Un vocabulaire commun. Dire « ici c'est un Observer » communique en trois mots une intention qui prendrait un paragraphe. Toute l'équipe se comprend instantanément.
  • Des solutions éprouvées. Ces problèmes ont été résolus mille fois ; inutile de réinventer une roue carrée.
  • Du découplage. Le fil rouge de presque tous les patterns : dépendre d'abstractions, pas de détails concrets, pour que les morceaux évoluent indépendamment.

Les trois familles

Le « Gang of Four » (le livre fondateur de 1994) range les 23 patterns en trois familles, selon la question à laquelle ils répondent :

Créationnels — « comment créer des objets ? » (Factory, Builder, Singleton…)

Structurels — « comment les assembler en structures ? » (Adapter, Decorator, Proxy…)

Comportementaux — « comment se parlent-ils ? » (Observer, Strategy, State…)

Le piège à éviter (le plus important)

🔨
Le syndrome du marteau d'or

« Quand on a un marteau, tout ressemble à un clou. » Le débutant qui découvre les patterns veut les caser partout — et transforme un programme simple en cathédrale d'abstractions. Chaque pattern a un coût : de l'indirection, des classes en plus, de la complexité. Ne le payez que lorsque le problème est réel, pas anticipé.

🎯
La bonne mentalité

On ne « place » pas un pattern : on le reconnaît quand le problème qu'il résout apparaît. Apprenez-les pour les repérer, et appliquez-les avec parcimonie. Le meilleur code reste le plus simple qui fasse le travail.

Créationnel · Patron 01 / 23

Factory Method

Intention — Déléguer la création d'objets à des sous-classes, en programmant contre une interface plutôt qu'une classe concrète.

Le problème

Votre code fait des new ClasseConcrète() un peu partout. Le jour où il faut un autre type d'objet, vous chassez chaque new dispersé dans la base — et vous ajoutez un if à chaque fois.

La solution

On isole la création derrière une méthode (la « factory method »). La classe de base utilise le produit via son interface ; chaque sous-classe décide quel produit concret fabriquer.

Création dispersée et conditionnelle : fragile, et chaque ajout viole le principe ouvert/fermé.
Le « quel concret » est localisé. Le code client reste stable, ouvert à l'extension.

🌍 Analogie — Un transporteur. RoadLogistics crée des camions, SeaLogistics crée des bateaux. La planification d'un trajet est identique ; seul le « véhicule » créé change.

Utilisez-le quand vous ne connaissez pas à l'avance les types concrets à créer, ou pour offrir un point d'extension aux utilisateurs de votre lib.

Le piège — une sous-classe par produit peut faire proliférer les classes. Pour un cas trivial, une simple fonction suffit.

Créationnel · Patron 02 / 23

Abstract Factory

Intention — Créer des familles d'objets liés (qui vont ensemble) sans préciser leurs classes concrètes.

Le problème

Vous avez plusieurs produits qui doivent être cohérents entre eux : des boutons et des cases « style macOS », ou « style Windows ». Vous voulez éviter de mélanger un bouton Mac avec une case Windows.

La solution

Une fabrique abstraite regroupe la création de toute une famille. Chaque fabrique concrète produit une famille cohérente.

🌍 Analogie — Un fabricant de meubles en kit. La gamme « Art déco » fournit chaise + table + canapé assortis ; la gamme « Moderne » aussi. On choisit une gamme, tout est cohérent.

Utilisez-le quand votre code doit fonctionner avec plusieurs familles de produits liés, en garantissant leur cohérence (thèmes UI, drivers de BDD, multi-plateformes).

Le piège — ajouter un nouveau type de produit oblige à modifier l'interface de fabrique et toutes ses implémentations. Lourd si la famille grossit souvent.

Créationnel · Patron 03 / 23

Builder

Intention — Construire un objet complexe étape par étape, en séparant la construction de la représentation finale.

Le problème

Le fameux constructeur « télescopique » : new Truc(a, b, undefined, null, true, undefined, "x"). Illisible, et chaque option facultative ajoute une surcharge.

La solution

Un builder propose des méthodes lisibles, chaînables, puis un build() final. On ne paie que pour les options qu'on choisit.

🌍 Analogie — Commander un burger : pain, steak, fromage, sauce… on coche les options une à une, et « valider » assemble le tout.

Utilisez-le quand un objet a beaucoup de paramètres optionnels, ou que sa construction se fait en plusieurs étapes (requêtes, configurations, documents).

Le piège — pour un objet à 2-3 champs, un objet de config { } en paramètre est plus simple. N'en faites pas une usine à gaz.

Créationnel · Patron 04 / 23

Prototype

Intention — Créer de nouveaux objets en clonant un exemplaire existant, plutôt qu'en les reconstruisant de zéro.

Le problème

Recréer un objet à l'identique demande de reconfigurer tous ses champs — parfois privés, ou coûteux à recalculer. Et vous voulez éviter de coupler votre code à sa classe concrète.

La solution

L'objet sait se cloner lui-même via une méthode clone().

🌍 Analogie — La photocopie. Plus rapide que de retaper le document : on duplique l'existant, puis on annote la copie.

Utilisez-le quand la création est coûteuse, ou que vous voulez dupliquer des objets sans dépendre de leurs classes concrètes (éditeurs graphiques, objets de jeu).

Le piège — attention aux références partagées : un clone superficiel copie les pointeurs, pas les objets imbriqués. Pensez clone profond si besoin.

Créationnel · Patron 05 / 23

Singleton

Intention — Garantir qu'une classe n'a qu'une seule instance et fournir un point d'accès global à celle-ci.

Le problème

Certaines choses doivent être uniques : un pool de connexions, une config applicative. On veut empêcher d'en créer plusieurs par accident.

La solution

Constructeur privé + une méthode statique qui crée l'instance à la demande et la réutilise ensuite.

⚠️
Le pattern le plus controversé

Le Singleton est souvent considéré comme un anti-pattern : c'est de l'état global déguisé. Il rend les tests difficiles (impossible de l'isoler ou de le remplacer), masque les dépendances et crée du couplage caché. Avant d'en mettre un, demandez-vous si une simple injection de dépendance ne ferait pas mieux le travail.

🌍 Analogie — Le gouvernement d'un pays : peu importe qui on interroge, il n'y en a qu'un, et c'est le point d'accès officiel.

Utilisez-le quand une ressource doit être strictement unique et partagée globalement (et que l'injection n'est pas praticable).

Le piège — testabilité et concurrence. En général, préférez injecter l'instance plutôt que d'y accéder via une statique globale.

Structurel · Patron 06 / 23

Adapter

Intention — Faire collaborer deux interfaces incompatibles en intercalant un traducteur.

Le problème

Une lib tierce (ou un vieux module) expose une API qui ne correspond pas à ce que votre code attend — et vous ne pouvez pas la modifier.

La solution

Un adaptateur implémente l'interface attendue par votre code, et traduit chaque appel vers la lib existante.

🌍 Analogie — L'adaptateur de prise électrique en voyage : il ne change ni la prise murale ni l'appareil, il les réconcilie.

Utilisez-le quand vous intégrez une lib externe, un système legacy, ou des APIs aux signatures divergentes derrière une interface unifiée.

Le piège — empiler les adaptateurs d'adaptateurs masque la dette. Parfois, mieux vaut assainir l'interface d'origine.

Structurel · Patron 07 / 23

Bridge

Intention — Découpler une abstraction de son implémentation pour que les deux varient indépendamment.

Le problème

Deux dimensions varient en même temps. Ex. : Télécommande (basique, avancée) × Appareil (TV, radio). En héritage classique, on explose en TVBasicRemote, RadioAdvancedRemote… combinatoire ingérable.

La solution

On sépare les deux hiérarchies : l'abstraction contient (compose) une implémentation et lui délègue le travail.

🌍 Analogie — Une télécommande universelle : un seul boîtier (abstraction) pilote n'importe quel téléviseur (implémentation), chacun évoluant de son côté.

Utilisez-le quand deux axes varient indépendamment (UI × plateforme, forme × rendu), pour éviter l'explosion combinatoire de sous-classes.

Le piège — souvent confondu avec l'Adapter. Le Bridge se conçoit en amont ; l'Adapter répond après coup à une incompatibilité.

Structurel · Patron 08 / 23

Composite

Intention — Composer des objets en arborescences, et traiter un élément simple et un groupe d'éléments de façon identique.

Le problème

Vous manipulez une hiérarchie (fichiers/dossiers, menus/sous-menus, formes/groupes) et vous truffez votre code de if (estUnDossier) … else ….

La solution

Feuilles et conteneurs implémentent la même interface. Un conteneur délègue récursivement à ses enfants.

🌍 Analogie — Un organigramme d'entreprise : on peut demander « combien de personnes ? » à un employé (1) comme à un département entier (sa somme).

Utilisez-le quand vous représentez des hiérarchies « tout/partie » et voulez les parcourir uniformément (arbres DOM, systèmes de fichiers, scènes graphiques).

Le piège — une interface trop large : si add() n'a aucun sens sur une feuille, il faut décider comment le gérer (erreur, no-op).

Structurel · Patron 09 / 23

Decorator

Intention — Ajouter des responsabilités à un objet dynamiquement, en l'enveloppant dans un autre objet de même interface.

Le problème

Vous voulez combiner des options (café + lait + sucre + chantilly). En héritage, vous créeriez une classe par combinaison… explosion garantie.

La solution

Chaque option est un décorateur qui enveloppe l'objet, expose la même interface, et ajoute son comportement avant/après de déléguer.

L'héritage fige les combinaisons à la compilation : ingérable dès quelques options.
Comportements composables à la volée : N briques couvrent toutes les combinaisons.
🧩
Ne pas confondre

Le pattern Decorator (envelopper un objet) n'est pas la même chose que les @decorators de TypeScript (une syntaxe pour annoter classes/méthodes). Mêmes mot, idées différentes — même si la syntaxe s'en inspire.

🌍 Analogie — S'habiller : t-shirt, puis pull, puis manteau. Chaque couche ajoute une fonction (chaleur) sans modifier les précédentes.

Utilisez-le quand vous voulez ajouter/retirer des comportements à la volée sans toucher la classe (flux de données : compression, chiffrement ; UI ; logging).

Le piège — de longues piles de décorateurs rendent le débogage et l'ordre d'application difficiles à suivre.

Structurel · Patron 10 / 23

Facade

Intention — Offrir une interface simple et unifiée à un sous-système complexe.

Le problème

Pour une tâche courante, le client doit orchestrer dix classes du sous-système, dans le bon ordre, avec les bons réglages. Couplage maximal.

La solution

Une façade expose une poignée de méthodes de haut niveau et cache toute la plomberie.

🌍 Analogie — Un standard téléphonique : vous dites « je veux réserver », sans savoir qui, en interne, gère le paiement, le stock et la logistique.

Utilisez-le quand vous voulez un point d'entrée simple vers une lib ou un sous-système touffu, ou découpler vos clients de ses détails.

Le piège — la façade peut devenir un « objet-dieu » qui sait tout faire. Gardez-la fine ; elle orchestre, elle n'implémente pas tout.

Structurel · Patron 11 / 23

Flyweight (poids-mouche)

Intention — Partager l'état commun entre une multitude d'objets pour économiser énormément de mémoire.

Le problème

Vous créez des millions d'objets quasi identiques (arbres d'une forêt, particules, caractères d'un texte). Chacun duplique des données lourdes → la RAM explose.

La solution

On sépare l'état intrinsèque (partagé, immuable) de l'état extrinsèque (propre à chaque objet). Une fabrique réutilise les flyweights partagés.

🌍 Analogie — Une police de caractères : la forme du « e » est stockée une fois ; le document ne retient que les positions où l'afficher.

Utilisez-le quand un très grand nombre d'objets partagent un état lourd et que la mémoire est un vrai goulot (rendu, jeux, éditeurs).

Le piège — optimisation pointue : complexifie le code. Ne l'introduisez qu'une fois la consommation mémoire mesurée comme problématique.

Structurel · Patron 12 / 23

Proxy

Intention — Substituer un objet par un intermédiaire de même interface, qui contrôle l'accès au vrai objet.

Le problème

Vous voulez ajouter du cache, du lazy-loading, du contrôle d'accès ou du logging autour d'un objet — sans modifier ni l'objet, ni le client.

La solution

Un proxy implémente la même interface, intercepte les appels, fait son travail, puis (éventuellement) délègue au vrai objet.

🌍 Analogie — Une carte bancaire : c'est un proxy vers votre compte. Même usage (payer), mais elle contrôle l'accès et la limite.

Utilisez-le quand vous voulez du cache, du chargement différé, du contrôle d'accès, des logs ou un objet distant — de façon transparente pour le client.

Le piège — proche du Decorator (même structure). La nuance : le Decorator ajoute des fonctions, le Proxy contrôle l'accès.

Comportemental · Patron 13 / 23

Chain of Responsibility

Intention — Faire transiter une requête le long d'une chaîne de gestionnaires, chacun décidant de la traiter ou de la passer au suivant.

Le problème

Une requête doit passer plusieurs étapes (authentification, quotas, validation, routage). Tout coder dans un seul bloc devient un monstre conditionnel.

La solution

Chaque étape est un maillon autonome ; on les chaîne, et la requête circule jusqu'à ce qu'un maillon réponde.

🌍 Analogie — Une demande de congé qui remonte : manager → RH → direction. Chacun valide à son niveau ou transmet plus haut.

Utilisez-le quand plusieurs objets peuvent traiter une requête et que le bon gestionnaire n'est connu qu'à l'exécution (middlewares, pipelines de validation, gestion d'événements).

Le piège — une requête peut traverser toute la chaîne sans être traitée. Prévoyez toujours un comportement par défaut.

Comportemental · Patron 14 / 23

Command

Intention — Transformer une requête en objet autonome — pour la paramétrer, la mettre en file, l'historiser ou… l'annuler.

Le problème

Vous voulez de l'undo/redo, des macros, ou découpler « qui déclenche » de « qui exécute ». Difficile avec de simples appels de méthode.

La solution

Chaque action devient un objet Command avec execute() (et souvent undo()). On peut alors les stocker, rejouer, inverser.

🌍 Analogie — Une commande au restaurant : le ticket (objet) circule du serveur à la cuisine. On peut l'empiler, la rejouer, l'annuler.

Utilisez-le quand vous avez besoin d'undo/redo, de files de tâches, de macros, ou de découpler l'émetteur d'une action de son exécuteur (boutons, raccourcis, jobs).

Le piège — beaucoup de petites classes de commandes. À doser ; pour un cas trivial, un callback suffit.

Comportemental · Patron 15 / 23

Iterator

Intention — Parcourir une collection séquentiellement sans exposer sa représentation interne.

Le problème

Vous voulez offrir un parcours uniforme de vos collections (liste, arbre, graphe) sans que le client connaisse leur structure.

La solution

En JS/TS, le pattern est natif : implémentez le protocole d'itération via [Symbol.iterator], et for…of / le spread fonctionnent gratuitement.

💡
Bonus TypeScript

Les générateurs (function* avec yield) sont la façon la plus concise d'écrire un itérateur : ils gèrent l'état du parcours pour vous, sans objet next() manuel.

🌍 Analogie — La télécommande « chaîne suivante » : vous passez d'une chaîne à l'autre sans savoir comment la télé les stocke.

Utilisez-le quand vous exposez vos propres structures de données au parcours, ou voulez plusieurs façons de parcourir (avant/arrière, filtré).

Le piège — pour un simple tableau, n'inventez rien : for…of et les méthodes natives suffisent largement.

Comportemental · Patron 16 / 23

Mediator

Intention — Centraliser les communications entre objets dans un médiateur, pour qu'ils ne se référencent plus directement.

Le problème

Quand chaque composant connaît tous les autres, on obtient un plat de spaghettis : couplage « tous-à-tous », impossible à faire évoluer.

La solution

Les composants ne parlent qu'au médiateur ; lui seul connaît tout le monde et orchestre les échanges.

🌍 Analogie — La tour de contrôle d'un aéroport : les avions ne se coordonnent pas entre eux, ils passent tous par la tour.

Utilisez-le quand un ensemble d'objets communiquent de façon désordonnée (composants d'un formulaire, salons de chat, UI complexe).

Le piège — le médiateur peut devenir un « objet-dieu » omniscient. Surveillez sa taille ; sinon vous déplacez le problème.

Comportemental · Patron 17 / 23

Memento

Intention — Capturer et restaurer l'état d'un objet (des instantanés) sans violer son encapsulation.

Le problème

Vous voulez des sauvegardes/restaurations (undo, points de contrôle) sans exposer tous les champs internes de l'objet au reste du code.

La solution

L'objet produit un memento opaque (un snapshot) et sait se restaurer à partir de l'un d'eux. Un « gardien » conserve l'historique sans en lire le contenu.

🌍 Analogie — Les points de sauvegarde d'un jeu vidéo : on enregistre l'état complet, et on y revient si ça tourne mal.

Utilisez-le quand vous avez besoin d'undo/snapshots/historique (souvent en duo avec Command) sans exposer l'intérieur de l'objet.

Le piège — garder beaucoup de snapshots complets coûte cher en mémoire. Pensez aux diffs ou à limiter l'historique.

Comportemental · Patron 18 / 23

Observer

Intention — Définir une dépendance un-à-plusieurs : quand un sujet change, tous ses abonnés sont notifiés automatiquement.

Le problème

Plusieurs parties de l'app doivent réagir à un changement (nouvelle donnée, événement). Si la source appelle chaque consommateur à la main, elle les connaît tous → couplage fort.

La solution

Les intéressés s'abonnent au sujet ; celui-ci les notifie sans connaître leurs détails. C'est le socle des systèmes d'événements et de réactivité.

La source connaît tous ses consommateurs ; chaque ajout la modifie.
Source et abonnés découplés : on branche/débranche sans modifier le sujet.

🌍 Analogie — Un abonnement à une newsletter : l'éditeur publie, tous les abonnés reçoivent, et il ignore qui ils sont.

Utilisez-le quand un changement doit se propager à plusieurs objets sans les coupler (events DOM, state management, réactivité, MVC).

Le piège — fuites mémoire si on oublie de se désabonner, et cascades de notifications difficiles à tracer. Pensez unsubscribe.

Comportemental · Patron 19 / 23

State

Intention — Changer le comportement d'un objet quand son état interne change — comme s'il changeait de classe.

Le problème

Un objet se comporte différemment selon son statut (brouillon, publié, archivé), et vous accumulez des switch (this.status) dans toutes ses méthodes.

La solution

Chaque état devient un objet qui encapsule son comportement. L'objet délègue à son état courant, et les états gèrent les transitions. C'est une machine à états propre.

🌍 Analogie — Un feu tricolore : rouge, orange, vert. Chaque couleur « sait » quelle est la suivante et quel comportement imposer.

Utilisez-le quand un objet a de nombreux états aux comportements distincts, et que les if/switch sur le statut prolifèrent (workflows, lecteurs, connexions).

Le piège — proche de Strategy structurellement. Différence : ici les états connaissent les transitions entre eux.

Comportemental · Patron 20 / 23

Strategy

Intention — Encapsuler une famille d'algorithmes interchangeables derrière une même interface, et les rendre permutables à l'exécution.

Le problème

Une méthode contient un gros if/else qui choisit un comportement selon un paramètre (mode de paiement, calcul de remise, tri). Ajouter un cas = rouvrir et risquer de casser le reste.

La solution

Chaque variante devient une stratégie isolée ; le contexte en reçoit une et l'utilise, sans connaître les détails. C'est le pattern pour tuer les conditionnels.

Toutes les variantes entassées dans une fonction qui grossit sans fin.
Algorithmes isolés et permutables. Ouvert à l'extension, fermé à la modification.

🌍 Analogie — Un GPS : « le plus rapide », « le plus court », « éviter les péages ». Même trajet à calculer, stratégies interchangeables.

Utilisez-le quand vous avez plusieurs façons de faire une même chose et voulez en changer dynamiquement (paiement, tri, compression, pricing).

Le piège — en JS, une stratégie peut être une simple fonction passée en paramètre — inutile de créer une classe par variante.

Comportemental · Patron 21 / 23

Template Method

Intention — Définir le squelette d'un algorithme dans une méthode, en laissant les sous-classes redéfinir certaines étapes sans changer l'ordre global.

Le problème

Plusieurs algorithmes partagent la même structure d'ensemble, mais diffèrent sur quelques étapes. Tout dupliquer mène à du copier-coller fragile.

La solution

La classe de base fige l'enchaînement (la « template method ») et déclare des étapes abstract que les sous-classes remplissent.

⚖️
Template Method vs Strategy

Les deux varient un algorithme. Template Method le fait par héritage (à la compilation, on remplit des trous). Strategy le fait par composition (à l'exécution, on échange un objet). Préférez souvent Strategy : plus souple, moins couplé.

🌍 Analogie — Une recette de base de gâteau : étapes fixes (mélanger, cuire), mais le parfum (chocolat, vanille) varie selon la déclinaison.

Utilisez-le quand plusieurs variantes partagent une ossature commune et ne diffèrent que par des étapes précises (pipelines, parseurs, frameworks).

Le piège — l'héritage crée un couplage fort base ↔ sous-classes. Si la structure bouge souvent, la composition (Strategy) vieillit mieux.

Comportemental · Patron 22 / 23

Visitor

Intention — Ajouter de nouvelles opérations à une hiérarchie d'objets sans modifier ses classes.

Le problème

Vous avez une structure stable (formes, nœuds d'un AST) et voulez lui ajouter des traitements variés (calculer l'aire, exporter, valider) sans polluer chaque classe à chaque nouvelle opération.

La solution

On externalise les opérations dans des visiteurs. Chaque élément « accepte » un visiteur et l'aiguille vers la bonne méthode (le « double dispatch »).

🌍 Analogie — Un inspecteur qui visite des bâtiments : selon sa spécialité (incendie, électricité), il applique son propre contrôle, sans modifier les bâtiments.

Utilisez-le quand une hiérarchie d'objets est stable mais que vous ajoutez souvent de nouvelles opérations dessus (compilateurs/AST, sérialisation, rapports).

Le piège — l'inverse coince : ajouter un nouveau type d'élément oblige à modifier tous les visiteurs. Réservez-le aux structures qui changent peu.

Comportemental · Patron 23 / 23

Interpreter

Intention — Représenter une grammaire simple par un arbre d'objets, et savoir interpréter ses phrases.

Le problème

Vous devez évaluer un mini-langage récurrent : expressions booléennes, règles métier, filtres. Le bricoler avec des chaînes et des conditions devient vite ingérable.

La solution

Chaque règle de grammaire devient une classe d'expression avec une méthode interpret(). On compose ces expressions en arbre, qu'on évalue.

🌍 Analogie — Une calculatrice : « 2 + 3 × 4 » est un arbre (×, puis +) que la machine parcourt pour donner le résultat.

Utilisez-le quand vous avez un petit langage stable à évaluer (règles, filtres, expressions), simple et bien borné.

Le piège — le moins utilisé du GoF. Pour une vraie grammaire, un générateur de parseur ou une lib dédiée sera bien plus robuste.

Pour finir

Comment choisir ?

Ne partez jamais d'un pattern. Partez d'un symptôme dans votre code, et laissez-le vous guider. Voici les correspondances les plus fréquentes.

Un gros if/else ou switch qui choisit un comportement
Strategy · State · Factory
Un constructeur à 8 arguments, dont la moitié optionnels
Builder
Il faut de l'undo / redo, ou une file d'actions
Command (+ Memento)
Plein d'objets doivent réagir à un changement
Observer
Une lib externe a une interface incompatible
Adapter
Ajouter des options sans cascade de sous-classes
Decorator
Cacher un sous-système touffu derrière un point d'entrée simple
Facade
Une arborescence à parcourir uniformément
Composite
Contrôler / différer / mettre en cache l'accès à un objet
Proxy
Une requête passe par plusieurs étapes de traitement
Chain of Responsibility
Des composants se parlent dans tous les sens
Mediator
Des algorithmes qui partagent la même ossature
Template Method
Trop d'objets identiques saturent la mémoire
Flyweight
🧭
Le bon ordre des choses

1. Écrivez la solution la plus simple. 2. Quand un vrai point de douleur apparaît (duplication, rigidité, couplage), 3. reconnaissez le pattern qui le soigne. Jamais l'inverse. Un pattern appliqué « au cas où » est de la complexité gratuite.

Pour finir

L'antisèche

Les 23 patterns, leur intention en une ligne. À épingler.

Créationnels — créer des objets
Factory MethodDéléguer la création à des sous-classes via une interface.
Abstract FactoryCréer des familles d'objets cohérents entre eux.
BuilderAssembler un objet complexe étape par étape.
PrototypeCréer en clonant un objet existant.
SingletonUne instance unique, point d'accès global (à manier avec prudence).
Structurels — assembler
AdapterRéconcilier deux interfaces incompatibles.
BridgeSéparer abstraction et implémentation pour qu'elles varient seules.
CompositeTraiter un élément et un arbre d'éléments de la même façon.
DecoratorAjouter des comportements en enveloppant l'objet.
FacadeUne interface simple sur un sous-système complexe.
FlyweightPartager l'état commun pour économiser la mémoire.
ProxyUn intermédiaire qui contrôle l'accès à un objet.
Comportementaux — communiquer
Chain of Resp.Faire transiter une requête le long d'une chaîne de gestionnaires.
CommandTransformer une requête en objet (file, undo, macro).
IteratorParcourir une collection sans exposer sa structure.
MediatorCentraliser les échanges entre objets.
MementoCapturer / restaurer un état (snapshots).
ObserverNotifier automatiquement une foule d'abonnés.
StateChanger de comportement selon l'état interne.
StrategyDes algorithmes interchangeables derrière une interface.
Template MethodSquelette figé, étapes personnalisables par les sous-classes.
VisitorAjouter des opérations à une hiérarchie sans la modifier.
InterpreterReprésenter et interpréter une petite grammaire.
🚀
Le mot de la fin

Les design patterns ne sont pas une médaille à exhiber : ce sont des outils de communication et des réponses à des douleurs réelles. Apprenez-les pour les reconnaître, gardez votre code simple, et ne dégainez le bon plan que quand le problème, lui, est bien là. Bon design ! 🔵