Ch. 2 — Observable et observateurs
Programmation événementielle, abonnement, notification, réaction : le patron Observer — comment un objet prévient d'autres objets d'un changement sans rien connaître d'eux.
La programmation événementielle
Un paradigme de programmation basé sur la gestion d'événements qui se produisent et sont gérés. Il est apparu avec les interfaces utilisateur graphiques (fenêtres, souris — voir R2.02 Introduction à l'interaction humain-machine), mais ne s'y limite pas : la synchronisation de threads l'utilise aussi.
Un événement, c'est « quelque chose » qui se produit en dehors du flot d'exécution normal. Un objet notifié peut choisir de le traiter — et plusieurs objets différents peuvent être notifiés du même événement et le traiter différemment.
Le patron Observateur
Le patron Observable–Observateurs (aussi appelé Listener) est le modèle générique de traitement des événements. Deux étapes distinctes le structurent :
Abonnement — faire savoir que l'on est intéressé par l'événement
Réaction — effectuer l'action associée lorsque l'événement se produit
C'est un patron de programmation objet qui diminue le couplage (la dépendance) entre les classes : l'observé ne dépend pas des observateurs — et le couplage faible favorise la maintenance à long terme du programme.
Le problème et la solution
Problème récurrent : limiter le couplage entre modules dont l'un (l'observateur) doit réagir aux variations de l'autre (l'observé) — avec, de plus, potentiellement plusieurs observateurs.
Solution générique :
- l'observable maintient une liste d'observateurs et les avertit de tout changement interne ;
- les observateurs ont la charge de s'abonner, se désabonner, et se mettre à jour quand ils reçoivent l'avertissement.
Faible couplage
L'observé ne dépend que d'une chose : ses observateurs répondent au message update(). Il gère
de la même façon un nombre quelconque d'observateurs — aucun, un seul, ou plusieurs.
Les défis du patron
- Comment prévenir les observateurs (dont le nombre et la nature sont inconnus) sans savoir a priori qui ils sont ? → la liste d'observateurs et l'interface commune.
- Chaque observateur réagit comme il le souhaite (exécute un code différent) → chacun
implémente
update()à sa manière.
Le cycle d'un événement en 5 étapes
Avant l'événement : les abonnés sont inactifs
Rien ne « tourne » pour les observateurs entre deux événements : ils sont notifiés uniquement
quand l'observable décide d'appeler notifyObservers(). C'est l'observable qui pousse
l'information, jamais les observateurs qui interrogent.
Les deux rôles en détail
| Rôle | Ce qu'il fournit | Ce qu'il maintient |
|---|---|---|
| Sujet observable | add(), remove(), notify() | la liste des observateurs abonnés, et un état interne (attributs) dont le changement produit l'événement |
| Observateur | update() — être informé et agir | rien de imposé : il réagit comme il veut |
Exemples d'états internes qui produisent un événement : le feu tricolore était rouge et devient vert ; un thread attendait des données et les reçoit (un attribut avant vide en contient maintenant).
Application type : le feu tricolore
Feu (observable) Observateur (interface)
- couleur : CouleurFeu + update(Observable) : void
+ add(Observateur) ↑ implémenté par
+ remove(Observateur) Piéton Véhicule
# notifyObservers() s'arrête au vert démarre au vert
↑ 0..* observersLe même événement — le passage au vert — produit deux réactions opposées, et le feu n'en sait
rien : il a juste appelé update(this) sur chaque abonné.
En Java, l'implémentation standard est dépréciée
java.util.Observable existait dans la bibliothèque standard, mais elle est dépréciée depuis
Java 9 car trop limitée. On écrit le patron à la main : deux petites classes, et on garde le
contrôle.
A retenir
Le patron Observateurs / Observé fonctionne en 4 étapes principales :
- abonnement (
add) ; - modification d'état ;
- notification (
notify) ; - mise à jour du ou des observateurs (
update).
ch2-observable-observateurs.pdf
R3.04 · Cours 2 — Fabien Delecroix, base de Nicolas Anquetil · 24 diapositives
Chargement du document…
Dernière mise à jour le
Ch. 1 — Patrons de conception
Ce qu'est un patron, les trois familles, et les six patrons de base : Fabrique simple, Décorateur, Composite, Singleton, Stratégie et ObjetNull — avec leurs exemples Java.
Ch. 3 — Modèle, Vue(s), Contrôleur(s)
Le patron architectural MVC : découpler l'interface de la logique métier — un modèle unique qui notifie, des vues qui affichent, des contrôleurs qui traduisent les actions de l'utilisateur.