Back

Création Flexible d'Objets avec le Pattern Builder en JavaScript

Création Flexible d'Objets avec le Pattern Builder en JavaScript

Vous avez une fonction qui crée des objets utilisateur. Elle commence avec trois paramètres, puis passe à cinq, puis sept. La moitié d’entre eux sont optionnels. Les appelants doivent se souvenir de l’ordre exact, et une seule erreur de position produit silencieusement un objet défectueux. C’est le problème que résout le Pattern Builder en JavaScript.

Points Clés

  • Le Pattern Builder construit des objets étape par étape en utilisant des méthodes setter chaînées et un appel final build(), remplaçant les listes d’arguments positionnels sujettes aux erreurs.
  • Une API fluide, où chaque setter retourne this, rend le site d’appel auto-documenté et indépendant de l’ordre.
  • Réservez ce pattern aux objets comportant de nombreux paramètres optionnels, une application de champs obligatoires ou des règles de validation. Pour les cas plus simples, utilisez des littéraux d’objets ou des fonctions factory.
  • La méthode build() est l’unique endroit pour valider les champs obligatoires et retourner un objet propre et figé, distinct du builder lui-même.

Qu’est-ce que le Pattern Builder en JavaScript ?

Le Pattern Builder est un patron de conception créationnel qui construit des objets étape par étape au lieu de tout créer d’un coup. Plutôt que de passer chaque valeur dans un seul appel de constructeur, vous chaînez des méthodes setter et finalisez la création avec une étape build() qui valide et retourne l’objet complété.

Ce n’est pas une solution universelle. Pour des objets simples avec deux ou trois champs bien définis, un simple littéral d’objet ou une fonction factory est plus propre. Le Pattern Builder trouve sa place lorsque la création d’objet implique :

  • De nombreux paramètres optionnels dont l’ordre n’a pas d’importance
  • Des règles de validation qui doivent s’exécuter avant l’utilisation de l’objet
  • Des champs obligatoires qui doivent être appliqués au moment de la création
  • Une construction en plusieurs étapes où les états intermédiaires ne doivent pas être exposés

Le Problème : La Pollution du Constructeur

Considérez ce pattern courant :

// ❌ Difficile à lire, facile de mélanger l'ordre des arguments
const request = new ApiRequest('GET', '/users', null, true, 5000, 'json')

Six arguments positionnels. Aucune étiquette. Aucune validation. Si vous inversez deux valeurs, rien ne vous avertit.

Un Exemple Propre du Pattern Builder en JavaScript

Voici une implémentation basée sur les classes utilisant une API fluide en JavaScript—où chaque setter retourne this, permettant le chaînage de méthodes :

class ApiRequestBuilder {
  constructor() {
    this.method = 'GET'        // sensible default
    this.url = null
    this.body = null
    this.timeout = 3000        // default timeout
    this.responseType = 'json'
  }

  setMethod(method) {
    this.method = method
    return this
  }

  setUrl(url) {
    this.url = url
    return this
  }

  setBody(body) {
    this.body = body
    return this
  }

  setTimeout(ms) {
    this.timeout = ms
    return this
  }

  build() {
    if (!this.url) {
      throw new Error('URL is required')
    }
    // Return a plain, frozen object—not the builder itself
    return Object.freeze({
      method: this.method,
      url: this.url,
      body: this.body,
      timeout: this.timeout,
      responseType: this.responseType,
    })
  }
}

// Usage
const request = new ApiRequestBuilder()
  .setUrl('/api/users')
  .setMethod('POST')
  .setBody({ name: 'Alice' })
  .build()

Chaque appel est auto-documenté. La validation s’exécute dans build() avant l’utilisation de l’objet. Les valeurs par défaut sont appliquées automatiquement. Notez que build() retourne un objet simple figé—pas le builder—ce qui maintient le résultat propre et empêche toute mutation accidentelle.

Builder vs. Alternatives Plus Simples

ScénarioMeilleure Approche
2-3 champs obligatoires, pas de validationLittéral d’objet ou fonction factory
Champs optionnels, pas de règlesParamètres nommés via createUser({ name, age })
Champs obligatoires + validation + valeurs par défautPattern Builder
Construction complexe en plusieurs étapesPattern Builder

Une fonction factory à paramètres nommés comme createRequest({ url, method = 'GET' }) gère proprement de nombreux cas. Optez pour un builder lorsque la logique de validation ou le séquencement rend cette fonction difficile à comprendre.

Une Note sur TypeScript

TypeScript peut rendre les builders significativement plus sûrs. Vous pouvez imposer que build() ne soit appelable qu’après l’appel des setters obligatoires, en utilisant des types conditionnels ou une interface step-builder. Si votre projet utilise TypeScript, cela vaut la peine d’explorer cette option—mais le pattern JavaScript de base fonctionne bien sans cela.

Conclusion

Utilisez le Pattern Builder lorsque la création d’objet comporte des règles qui doivent être appliquées, et non comme stratégie par défaut de création d’objets. L’API fluide rend le site d’appel lisible, l’étape build() rend la validation explicite, et les valeurs par défaut réduisent le bruit. Pour tout ce qui est plus simple, une fonction factory ou un simple littéral d’objet est le bon outil.

FAQ

Un objet d'options regroupe des paramètres nommés, ce qui résout le problème des arguments positionnels. Un builder ajoute une étape de construction où vous pouvez valider les champs obligatoires, appliquer des contraintes et figer le résultat avant son utilisation. Si vous avez besoin de ces garanties, un builder est le meilleur choix. Si vous avez simplement besoin de clés nommées avec des valeurs par défaut, un objet d'options est plus simple.

Oui, mais soyez prudent. Après avoir appelé build, le builder conserve toujours l'état de la configuration précédente. Vous devez réinitialiser chaque champ ou créer une nouvelle instance de builder pour chaque objet. Créer une nouvelle instance à chaque fois est l'approche la plus sûre et la plus prévisible.

Cela peut être le cas. Si votre objet n'a que quelques champs bien connus et aucune règle de validation, un simple littéral d'objet ou une fonction factory avec des paramètres nommés est plus propre. Le Pattern Builder devient rentable lorsque le nombre de champs optionnels augmente, lorsque les valeurs par défaut interagissent, ou lorsque la création nécessite des contraintes appliquées.

Object.freeze empêche les propriétés de premier niveau de l'objet retourné d'être modifiées après la création. Cela maintient le résultat construit prévisible et en lecture seule, ce qui est particulièrement utile lorsque l'objet est transmis à travers plusieurs couches de code. Cela établit une frontière claire entre le temps de configuration à l'intérieur du builder et le temps d'utilisation à l'extérieur.

Truly understand users experience

See every user interaction, feel every frustration and track all hesitations with OpenReplay — the open-source digital experience platform. It can be self-hosted in minutes, giving you complete control over your customer data. . Check our GitHub repo and join the thousands of developers in our community..

OpenReplay