Bienvenue dans le premier chapitre de la dernière partie de ce cours. Dans cette partie, vous découvrirez les Behavioral Design Patterns, autrement dit des design patterns dédiés à la communication entre des objets.
Ajoutez un produit à vos envies en utilisant un Observer
Nous allons ouvrir le bal avec un pattern très connu et très répandu : l’Observer Pattern (ou observable, en bon français). Regardez l’issue liée à ce chapitre avant de poursuivre la lecture. :)
Si je dois résumer l’issue en quelques mots : il vous est demandé de réaliser un système de mise en envie. Autrement dit, lorsque vous allez cliquer sur l’une des icônes de cœur de l’un des films, l’icône va changer de couleur et le compteur “nombre d’envies” va évoluer :
Dans la vidéo ci-dessus :
Si je clique sur l’icône Total Recall, le cœur revient à son état initial et le compteur d’envies tombe à 1.
Si je clique sur l’icône Batman & Robin, le cœur se remplit et le compteur d’envies monte à 3.
Si vous faites du JavaScript depuis quelque temps et que vous avez déjà codé quelques projets avec le DOM, il y a une chose qui doit attirer votre attention. :) Pour réaliser cette fonctionnalité, on va devoir utiliser un Event Listener.
Un Event Listener ?
C’est ça !
On peut traduire ça en français comme un “écouteur d'événements". Autrement dit, grâce à la méthode addEventListener
, nous allons écouter un type d'événement sur un nœud. Cet événement peut être le clic de la souris, le scroll, appuyer sur une touche précise (la barre espace, par exemple).
Mais, alors, pourquoi est-ce que je prends le temps de vous le représenter ? Vous vous souvenez peut-être qu’en début de cours, je vous ai dit que vous utilisiez déjà des design patterns sans le savoir ? Nous y sommes. :)
En fait, la méthode addEventListener
est un Observer Pattern : vous allez écouter un objet et une fois que cet objet change d’état, par exemple au moment de remplir un formulaire, vous allez pouvoir déclencher un bout de code, le plus souvent via une fonction callback.
Identifiez les caractéristiques de l’Observer Pattern
Un Observer Pattern est composé des acteurs suivants :
Vous avez le Sujet. Ce dernier maintient la liste des observateurs. Il permet à des observateurs de s’abonner ou de se désabonner. Une fois que l’état du sujet change, grâce à ce système d’abonnement, les observateurs vont être notifiés que l’état du sujet a changé.
Puis, vous avez le ou les Observers. Lorsqu’ils vont être notifiés d’un changement d’état du sujet, ils vont pouvoir déclencher un script. Dans notre cas, ce sera la modification du compteur d’envies. Ici, il est important de voir qu’il peut y avoir plusieurs observateurs différents pour un même sujet.
Mais est-ce que ces Observateurs peuvent être le même type d’objets, ou est-ce qu’ils réalisent la même fonctionnalité, par exemple, afficher du texte ?
Non, et c’est tout l’intérêt !
Dans le cadre de notre application, nous allons nous servir de ce pattern pour augmenter un compteur d’envies. Cela dit, on pourrait aller beaucoup plus loin. On pourrait, par exemple, avoir :
Un Observer qui se chargerait de faire un call API pour enregistrer l'œuvre mise en envie en base de données ;
Un autre Observer qui se chargerait d’envoyer un e-mail à l’utilisateur pour lui dire qu’il vient de mettre un film en envie ;
Et enfin, un dernier Observer qui se chargerait de vérifier si l'œuvre est bien disponible sur Netflix.
En fait, quand on parle d’Observers, on dit souvent qu’ils permettent de “découpler” une architecture (ou une infrastructure). Plutôt que de faire grossir un objet en lui ajoutant une nouvelle fonctionnalité, en utilisant un Decorator par exemple, on va plutôt créer des objets qui vont communiquer entre eux : on aurait donc plein de “petits” objets qui feront des tâches spécifiques.
Implémentez un Observer Pattern
À la différence des précédents chapitres, je ne vais pas créer ici de dossier Observer. Je vais plutôt avoir tendance à créer et nommer des objets en fonction des actions qu’ils réalisent. Par exemple un objet Wishlist.
Dans le cadre de notre issue, j’aurai tendance à faire :
Un dossier
/js/wishlist
;Un fichier
/js/wishlist/Subject
, ce qui me permet de préciser, via le nommage, qu’on va avoir un Sujet qui va notifier les Observers ;Un fichier
/js/wishlist/Counter
qui contiendra mon Observer.
Je vais ici travailler sur JS Bin pour vous montrer un exemple d’implémentation d’un Observer Pattern. Je créerai un objet Sujet et deux Observers différents. Cela vous donnera l’opportunité de voir comment des Observers dialoguent entre eux.
Vous pouvez retrouver le code source de cet exemple ici.
À vous de jouer !
Maintenant que vous savez comment créer un Observer, il est temps de pratiquer un peu de votre côté. Pour ce faire, je vous ai préparé une partie du travail :
Les fichiers
/js/wishlist/Counter.js
et/js/wishlist/Subject.js
existent déjà et ont déjà été liés au fichierindex.html
.Le cœur a été intégré sur les maquettes ; idem pour le compteur.
Vous n’avez pas non plus besoin de modifier l'
index.html
.Essayez de vous concentrer sur les fichiers
js/App.js
,js/templates/MovieCard.js
,js/wishlist/Subject.js
etjs/wishlist/Counter.js
.
N’oubliez pas de vous référer à cette issue GitHub puisqu’elle contient des précisions sur les fonctionnalités attendues. Ne paniquez pas si vous n’y arrivez pas du premier coup, c’est normal : vous êtes ici sur un design pattern assez complexe.
Une fois que vous avez terminé, le code source contenant la solution de cet exercice se trouve sur la branche partie-4/chapitre-1-fin
.
En résumé
L’Observer Pattern crée un objet qui va notifier d’autres objets de votre code au moment de changements d’état.
Vous utilisez déjà ce type de design pattern via les Event Listeners et les méthodes
addEventListener
.L’Observer Pattern permet de découpler une architecture : plutôt que d’alourdir et de complexifier des objets existants, vous faites dialoguer des objets entre eux.
Un Observer Pattern est plus complexe qu’un Decorator Pattern ou qu'un Constructor Pattern. Essayez de vous familiariser avec les autres avant de passer sur celui-là.
Félicitations, vous venez de terminer un gros morceau du cours. Comme toujours, si vous n’avez pas encore totalement compris, n’hésitez pas à relire cette partie un peu plus tard (idéalement après avoir pratiqué sur un projet).