Design Pattern
Introduction

Choisir le bon pattern

Partir du problème, pas du pattern

Le problème

Connaître les patterns individuellement ne suffit pas. La vraie compétence, c'est de regarder du code et de savoir lequel appliquer, ou de reconnaître qu'aucun ne s'impose.

La mauvaise approche : "j'ai appris Factory aujourd'hui, je vais le mettre quelque part". Le pattern devient une solution qui cherche un problème.

La bonne approche : partir de la douleur dans le code.

Partir du symptôme

Tu observes ça dans le codeTu penses à ça
La même valeur hardcodée à 5 endroitsSingleton, centraliser la config
new MonObjet() dupliqué partout avec de la logique dedansFactory, encapsuler la création
Le composant parle directement à une API externeAdapter, abstraire la source de données
Ajouter une feature oblige à modifier une classe existanteDecorator, enrichir sans toucher
Des if/else sur un comportement qui change selon le contexteStrategy, extraire l'algorithme
Un composant doit "réagir" à des changements sans être couplé à la sourceObserver, notifier sans dépendance directe
Des actions qui devraient être réversibles ne le sont pasCommand, encapsuler l'action et son inverse

Questions à se poser

Le problème concerne la création d'objets ? → Singleton, Factory, Builder

Le problème concerne la structure, comment les objets sont composés ? → Adapter, Decorator, Facade, Proxy

Le problème concerne la communication entre objets ? → Observer, Strategy, Command

Ce que les patterns ne sont pas

Les patterns GoF ne couvrent pas tout. Beaucoup de problèmes en front-end se résolvent autrement :

  • Un composant trop gros → découpage en composants, pas nécessairement un pattern GoF
  • De la duplication de logique → un hook custom ou une fonction utilitaire
  • De la prop drilling → Context API ou un store (qui est lui-même un Observer, mais idiomatique React)

Plaquer un pattern GoF sur un problème React standard, c'est souvent de la surconception.

La règle d'or

Un pattern se justifie quand il supprime une douleur concrète. Si tu n'arrives pas à expliquer en une phrase le problème qu'il résout dans ton code, c'est qu'il n'a probablement pas sa place.

// ✗ Factory sans raison
class UserFactory {
  static create(name: string) {
    return { name }; // juste un objet littéral déguisé
  }
}

// ✓ Factory justifiée, la création est complexe et réutilisée
class PokemonFactory {
  static create(raw: any): Pokemon {
    return {
      id: raw.id,
      name: raw.name,
      sprite: raw.sprites.front_default,
      types: raw.types.map((t: any) => t.type.name),
      stats: {
        hp: raw.stats[0].base_stat,
        attack: raw.stats[1].base_stat,
        defense: raw.stats[2].base_stat,
        speed: raw.stats[5].base_stat,
      },
    };
  }
}

La différence : dans le deuxième cas, sans Factory, cette logique serait dupliquée et couplée au composant qui fait le fetch.