• 10 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 02/03/2022

Déléguez la création des objets avec le Factory Pattern

Utilisez un Factory Pattern pour gérer les données de deux API différentes

Grande nouvelle, notre projet Filmo Patterns va accueillir des films provenant d’une deuxième source de données. Pour vous simplifier la vie, j’ai créé cette issue GitHub. Je vous invite à la découvrir avant de passer à la suite.

C’est bon, vous avez bien lu l’issue ? Alors, on peut continuer. ;)

Voici un résumé de notre problématique :

  • Nous avons un premier fichier JSON (  data/new-movie-data.json  ). C’est grâce à ce fichier que nous affichons actuellement nos films d’Arnold Schwarzenegger sur le projet.

  • Nous avons un deuxième fichier JSON (  data/external-movie-data.json  ). C’est ce deuxième fichier que nous devons intégrer à notre projet. Il comprend des films de Sylvester Stallone.

Il y a aussi le fichier   data/old-movie-data.json, non ?

Oui, tout à fait !

J’ai gardé ce fichier pour vous montrer un cas d’exemple dans la suite de ce chapitre. Mais encore un peu de patience ! Pour le moment, je souhaite que vous vous posiez la question : comment peut-on intégrer ce nouveau fichier JSON sans avoir à modifier grandement notre code ?

Est-ce qu’on ne peut pas modifier la classe  templates/MovieCard.js  ? Quitte à en créer une nouvelle ?

Non, parce que pour le coup, ce fichier nous sert plutôt de template (on dit aussi vue), et affiche les données. Il ne doit pas vraiment contenir de la logique, et plus particulièrement de la logique de formatage. Son rôle est uniquement d’afficher l’affiche du film, son nom, sa durée et sa date de sortie.

OK, est-ce qu’on ne pourrait pas ajouter de nouvelles règles dans notre Constructor Pattern   models/Movie.js  ?

Oui mais non. :)

Sur le papier, ça peut sembler être une bonne idée, parce que tout notre formatage est réalisé à l’intérieur de ce fichier. Cela dit, ça risque d’alourdir le code de la classe et de le rendre aussi moins lisible.

Voilà ce que nous allons faire : nous allons créer un nouveau Constructor Pattern pour gérer ce nouveau formatage de données, et nous allons nous servir d’un Factory Pattern pour l’implémenter.

Identifiez les caractéristiques du Factory Pattern

Dans un rectangle au centre, MoviesFactory Creator est labellisé comme une constructor. Il relie respectivement par une flèche OldMovie et Movie
Représentation du factory Pattern

Dans le diagramme ci-dessus, vous pouvez voir que le Factory Pattern est composé des éléments suivants :

  • La Factory. Elle va récupérer les données qui lui seront passées, et va déléguer la création et le formatage de ces données au bon Constructor. Ici, les données sont celles des fichiers   new-movie-data.json  et   external-movie-data.json  .

  • Les objets qui vont être créés par la Factory. Dans notre cas, nous allons avoir deux Constructor Patterns. Un qui existe déjà (Movie.js) et l’autre qui reste à créer. Ils vont formater la donnée pour nous. Ils vont l’envoyer dans notre fichier de template   MovieCard  sans que ce dernier ait de traitements supplémentaires à réaliser.

Du coup, ce design pattern permet de déléguer la création d’un objet ?

C’est ça !

Le rôle du Factory Pattern est de faciliter la création d’objets au sein d’une base de code. On va s’en servir pour créer et gérer différents types d’objets qui présentent des caractéristiques similaires. Dans la pratique, on peut, par exemple, s’en servir pour :

  • Gérer différentes sources de données. Dans le cas de notre application, ces données proviennent de deux fichiers différents. Cela dit, ces données pourraient aussi venir d’une API et d’une base de données ;

  • Gérer des basculements de données. Autrement dit, passer de données mockées (comme c’est le cas actuellement dans notre projet) à des données provenant d’une API.

Et du coup, côté code, ça donne quoi ?

Alors, côté Factory, le code est assez “simple” :

class MoviesFactory {
   constructor(data, type) {
       // Si le type correspond à l'ancienne API, alors retourne-moi l'ancien formatage
       if (type === 'oldApi') {
           return new OldMovie(data)
       // Sinon retourne-moi le nouveau formatage
       } else if (type === 'newApi') {
           return new Movie(data)
       // Une bonne pratique est de déclencher une erreur si le format n'est pas reconnu
       } else {
           throw 'Unknown type format'
       }
   }
}

Je retourne le Constructor   OldMovie  ou   Movie  en fonction du type d’objets que j’ai passés. Ici, le paramètre   type  peut être   oldApi  ou   newApi  . Puis dans mon fichier   App.js  , au lieu d’appeler directement le constructor   Movie  ou   OldMovie  , j’appelle ma Factory :

const OldMovies = oldMoviesData
     .map(movie => new MoviesFactory(movie, 'oldApi'))

Implémentez un Factory Pattern

Pour implémenter un Factory Pattern, j’ai tendance à créer un nouveau dossier, que je vais appeler   factories  . Et je vais aussi créer un fichier   MoviesFactory  .

Bon, comme toujours, rien ne remplace la pratique !

Nous allons implémenter un Factory Pattern pour afficher les films contenus dans les fichiers   data/old-movie-data.json  et   data/new-movie-data.json  .

Mais les films vont s’afficher en double, non ?

Tout à fait. :)

Mais ça va me permettre de vous montrer un exemple d’implémentation. À la fin du chapitre, ce sera à vous de jouer !

Si vous avez bien suivi la vidéo, votre code devrait être conforme au code de la branche partie-2/chapitre-2-exercice  .

À vous de jouer !

OK, c’est maintenant à vous de jouer !

Vous vous souvenez de l’issue GitHub en début de chapitre ? Vous allez devoir l’implémenter !

Si je résume cette issue, voici ce que vous devez faire :

  • Utilisez les données contenues dans le fichier   data/external-movie-data.json  . Ces données correspondent à des films de Sylvester Stallone. Vous allez donc devoir créer dans le fichier  App.js  un nouvel appel API via notre classe   MovieApi  . Vous pouvez vous inspirer des appels API déjà présents dans le fichier.

  • Créez un Constructor Pattern pour formater les données récupérées. Vous ne devez pas toucher au fichier   templates/MovieCard.js  .

  • Mettez à jour le Factory   MoviesFactory  pour qu’il vous retourne le bon objet.

Allez, c’est pas mal de boulot, mais tout va bien se passer. :)

Une fois que vous aurez trouvé la solution, ou si vous êtes bloqué, je vous invite à regarder ma correction dans la vidéo ci-dessous.

Le code source contenant la solution de cet exercice se trouve sur la branche partie-2/chapitre-2-fin  .

Notre projet Filmo Patterns affiche maintenant les films d’Arnold Schwarzenegger et de Sylvester Stallone
Notre projet Filmo Patterns affiche maintenant les films d’Arnold Schwarzenegger et de Sylvester Stallone

En résumé

  • Le Factory Pattern est utilisé pour déléguer la création d’objets. Au lieu de créer vos objets “en direct”, vous passez par un autre objet (la Factory) qui va se charger de créer le bon objet.

  • Pour créer un Factory Pattern, vous devez créer un dossierfactories et instancier les objets directement depuis le bon constructeur de la Factory.

  • Attention à l’utilisation de ce dernier, qui a tendance à fortement complexifier la base de code.

Vous connaissez maintenant votre deuxième design pattern, et surtout vous savez comment implémenter deux design patterns en même temps ! Dans le prochain chapitre, vous découvrirez un design pattern très commun : le Singleton !

Exemple de certificat de réussite
Exemple de certificat de réussite