Design patterns : ceux qui comptent vraiment (avec exemples en Java)
Pas les 23 patterns du Gang of Four récités de mémoire : les cinq que nous utilisons réellement en production, des exemples en Java, les cas où appliquer un pattern est une erreur, et pourquoi les entretiens posent encore la question.
Michele Cimmino · CEO & Academy Director, Lasting Dynamics · 25 août 2026 · 7 min read
Les design patterns ont un problème de réputation, et ils l'ont mérité : des générations de développeurs les ont appris comme un catéchisme — 23 noms du Gang of Four à réciter en entretien — puis les ont appliqués au hasard, produisant des AbstractSingletonProxyFactoryBean et autres créatures que personne n'avait demandées. Chez Lasting Dynamics, nous utilisons des patterns tous les jours et nous les enseignons dans notre academy, mais nous les enseignons pour ce qu'ils sont : un vocabulaire partagé pour des problèmes récurrents, pas des points à collectionner.
Voici la version pratique : les patterns vers lesquels nous tendons vraiment la main, des exemples en Java, et — tout aussi important — les cas où tendre la main est l'erreur.
Ce qu'est réellement un design pattern
Un design pattern est une solution nommée à un problème de conception récurrent. La valeur n'est pas dans la solution (souvent évidente une fois qu'on l'a vue) — elle est dans le nom partagé. Quand quelqu'un dit « j'en ferais une Strategy » en code review, l'équipe se transmet toute une conception en trois mots. Les patterns sont de la compression de communication avant d'être de la technique.
Le corollaire honnête : un pattern appliqué là où le problème n'existe pas n'est pas de l'architecture — c'est un coût. La bonne question n'est jamais « quel pattern puis-je utiliser ici ? » mais « quel problème ai-je, et porte-t-il déjà un nom ? »
Les cinq que nous utilisons vraiment
1. Strategy — quand l'algorithme doit être interchangeable
Le pattern le plus utile qui soit, et le plus simple : des comportements interchangeables derrière une seule interface.
interface PricingStrategy {
BigDecimal price(Order order);
}
class StandardPricing implements PricingStrategy { /* ... */ }
class BlackFridayPricing implements PricingStrategy { /* ... */ }
class Checkout {
private final PricingStrategy pricing;
Checkout(PricingStrategy pricing) { this.pricing = pricing; }
}
Chaque chaîne de if (type == X) ... else if (type == Y) qui s'allonge à chaque sprint est une Strategy qui demande à naître. En Java moderne, une lambda ou une Function<Order, BigDecimal> suffit souvent — le pattern, c'est l'idée, pas la hiérarchie de classes.
2. Factory Method — quand la création est une décision
Si construire un objet implique de la logique (quelle implémentation ? quelles dépendances ?), cette logique mérite exactement un seul foyer :
class NotifierFactory {
Notifier forChannel(Channel c) {
return switch (c) {
case EMAIL -> new EmailNotifier(smtp);
case SMS -> new SmsNotifier(twilio);
case PUSH -> new PushNotifier(fcm);
};
}
}
Le vrai bénéfice : le code client dépend de Notifier, jamais des classes concrètes. C'est le frère qui travaille de l'inversion de dépendances que nous couvrons dans notre guide de clean architecture.
3. Observer — quand quelque chose se produit et que d'autres doivent le savoir
Les événements de domaine : une commande est confirmée, et le stock, l'email et l'analytics doivent réagir — sans que Order connaisse aucun d'eux. En Java, tu le rencontreras plus souvent sous forme de listeners, d'événements Spring ou d'un message broker que d'une implémentation écrite à la main, mais la conception est la même : l'émetteur ne connaît pas les écouteurs. C'est le pattern qui garde le couplage bas dans les systèmes qui grandissent.
4. Adapter — quand le monde extérieur ne parle pas ta langue
Toute intégration sérieuse en a un : la bibliothèque de paiement a son API, ton domaine a son interface, l'adapter traduit. La valeur stratégique, c'est la frontière : quand le fournisseur change son API (il le fera), tu réécris l'adapter, pas le domaine.
5. Decorator — quand tu ajoutes une responsabilité sans toucher à la classe
Logging, cache, retries autour d'un service existant :
class CachedCatalog implements Catalog {
private final Catalog inner;
private final Map<String, Product> cache = new ConcurrentHashMap<>();
public Product byId(String id) {
return cache.computeIfAbsent(id, inner::byId);
}
}
Même interface, comportement enrichi, composable à volonté. (C'est aussi la conception derrière la moitié de l'écosystème Java, des flux d'I/O aux middlewares.)
Celui dont il faut se méfier : Singleton
Il mérite d'être couvert parce que les entretiens posent encore la question : le Singleton garantit une instance globale unique. En pratique, en 2026, c'est presque toujours un signal d'alarme — de l'état global déguisé, du code difficile à tester, des dépendances cachées. Si tu as besoin d'une seule instance, ton conteneur d'injection de dépendances te la fournit (Spring le fait par défaut, avec un scope singleton managé — une tout autre chose). Savoir expliquer ça en entretien vaut plus que savoir l'implémenter.
Quand un pattern est la mauvaise décision
La règle que nous donnons dans l'academy : le problème d'abord, le pattern ensuite — jamais l'inverse.
- Si le code est plus simple sans le pattern, le pattern est faux. Trois implémentations de
PricingStrategydont deux vides, c'est unifen costume. - Les patterns s'extraient, ils ne s'anticipent pas : le bon moment pour une Strategy, c'est la deuxième variante réelle, pas la première imaginée.
- Si tu ne sais pas nommer le changement futur contre lequel le pattern protège, tu fais de la cérémonie.
Une note pour l'ère des agents IA : des outils comme Claude Code génèrent des patterns avec enthousiasme — demande une factory et tu en auras une magnifique, nécessaire ou pas. Le jugement sur le fait qu'elle soit nécessaire reste le tien. Même principe que dans notre guide du vibe coding : l'IA remplit la structure ; décider de la structure, c'est le métier.
Pourquoi les entretiens posent encore la question (et comment répondre)
Parce que les patterns sont un proxy rapide du vocabulaire de conception. La réponse qui porte n'est pas la liste des 23 — c'est « j'utiliserais une Strategy ici parce que cette branche grandit à chaque sprint, et je n'utiliserais pas un Singleton parce que… ». Le parce que est le signal ; le nom n'est que l'étiquette.
C'est exactement comme ça que nous les entraînons à la Lasting Dynamics Academy : les design patterns sont dans le curriculum à côté de l'architecture, des RDBMS et des tests, appliqués sur des tâches réelles et challengés dans la review hebdomadaire avec le mentor — où « quel pattern as-tu utilisé et pourquoi » est une vraie question, chaque semaine. Gratuit, entièrement à distance, sélectif, avec une offre d'emploi pour tous ceux qui terminent. Si tu veux que ton vocabulaire de conception devienne du jugement, les candidatures sont ouvertes.
FAQ
Faut-il apprendre les 23 ? Non. Apprends bien les cinq ci-dessus, plus les deux ou trois que ta stack utilise vraiment (en Java : Builder et Template Method reviennent souvent). Reconnais les autres quand tu les croises ; personne ne les utilise tous.
Les design patterns sont-ils encore pertinents avec les langages modernes ?
Oui, mais beaucoup se sont dissous dans le langage : des lambdas au lieu de Strategies formelles, Optional au lieu de Null Object, des records pour les value objects. Les problèmes que les patterns résolvaient existent toujours ; les solutions se sont juste allégées. Reconnaître le problème reste la compétence.
Design patterns et architecture, est-ce la même chose ? Deux échelles du même instinct : les patterns organisent les classes et les objets ; l'architecture organise les modules et les frontières. Un système peut avoir des patterns parfaits et une architecture épouvantable — et inversement. Il te faut les deux, et c'est pourquoi l'academy les enseigne ensemble.