Cours BUT Info

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.
L'observable ne connaît de ses observateurs qu'une chose : ils répondent au message update(). Le nombre et la nature des observateurs peuvent changer à l'exécution sans toucher à l'observable.

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

Le cycle complet, avec le fil rouge du cours : un feu tricolore observable, observé par des véhicules et des piétons qui réagissent différemment au même événement.

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ôleCe qu'il fournitCe qu'il maintient
Sujet observableadd(), remove(), notify()la liste des observateurs abonnés, et un état interne (attributs) dont le changement produit l'événement
Observateurupdate() — être informé et agirrien 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..* observers

Le 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 :

  1. abonnement (add) ;
  2. modification d'état ;
  3. notification (notify) ;
  4. mise à jour du ou des observateurs (update).

ch2-observable-observateurs.pdf

R3.04 · Cours 2 — Fabien Delecroix, base de Nicolas Anquetil · 24 diapositives

Consultation seule — téléchargement désactivé

Chargement du document…

Dernière mise à jour le

Sur cette page