$ which-

Les design patterns les plus courants

8 patterns que tu croises vraiment en pratique — quand les utiliser, quand ils ne sont que du sur-engineering.

8 patterns·1 réflexe·référence, pas comparatif
Réflexe

Préfère la composition à l'héritage. N'introduis un pattern que si le problème concret s'est déjà présenté au moins deux fois — pas de pattern posé par anticipation, ça s'appelle du sur-engineering.

Singleton / créational

Une seule instance, accès global.

Choisir si : besoin garanti d'une instance unique partagée (config, connexion, cache en mémoire) et un point d'accès global assumé.

instance uniqueétat globalcreational

Éviter si : la plupart des cas → couplage global, tests difficiles à isoler ; une dépendance injectée fait souvent mieux.

Factory Method / créational

Déléguer la construction, pas le choix du client.

Choisir si : le type exact à instancier dépend du contexte ou de la config, et le code appelant ne doit pas connaître les classes concrètes.

constructionpolymorphismecreational

Éviter si : une seule implémentation existe et n'en aura pas d'autre → une fonction ou un constructeur direct suffit.

Strategy / comportemental

Algorithmes interchangeables derrière une interface commune.

Choisir si : plusieurs variantes du même comportement (tri, tarification, validation) doivent être choisies et changées à la volée.

interchangeablecompositionbehavioral

Éviter si : une seule variante existe et restera stable → un if/switch direct est plus lisible qu'une hiérarchie de classes.

Observer / comportemental

Notifier des abonnés sans les connaître.

Choisir si : plusieurs parties du système doivent réagir à un changement d'état sans être couplées à sa source (événements UI, pub/sub interne).

découplageévénementsbehavioral

Éviter si : un seul abonné fixe et connu → un appel direct est plus simple à tracer qu'une notification indirecte.

Decorator / structurel

Ajouter du comportement par empilement, pas par héritage.

Choisir si : des responsabilités additionnelles (logging, cache, validation) doivent se combiner librement autour d'un objet existant.

compositionwrappingstructural

Éviter si : une seule combinaison de comportements suffira toujours → l'empilement de wrappers nuit à la lisibilité pour rien.

Adapter / structurel

Faire parler deux interfaces incompatibles.

Choisir si : intégrer une lib externe ou un legacy dont l'interface ne correspond pas à celle attendue par le reste du code.

interoplegacystructural

Éviter si : tu contrôles les deux côtés de l'interface → aligne-les directement plutôt que d'ajouter une couche.

Repository / accès aux données

Isoler le domaine de la persistance.

Choisir si : le domaine ne doit pas dépendre du moteur de stockage (SQL, API, fichier) et tu veux pouvoir le mocker en test.

persistanceabstractiontestabilité

Éviter si : app CRUD simple avec un seul accès direct à la DB → la couche ajoute de l'indirection sans bénéfice réel.

Dependency Injection / architectural

Recevoir ses dépendances, ne pas les construire.

Choisir si : un composant a des dépendances qui varient selon le contexte (test, environnement) ou qui doivent rester remplaçables.

découplagetestabilitéinversion de contrôle

Éviter si : petit script sans variation de dépendances → instancier directement évite un conteneur DI superflu.