Vous êtes sur la page 1sur 27

Observateur

Exemple de problématique :
Abonnement dans un flux RSS
1. Un éditeur se lance dans les affaires de communication électronique et
commence à diffuser des flux RSS sur les nouveaux produits
2. vous souscrivez un abonnement à ce Flux RSS
3. Chaque fois qu’il y’a un nouveau produit, vous recevez une notification.
Et tant que vous êtes abonné, vous recevez les nouvelles éditions.
4. Quand vous ne vouliez pas de ces Pub (Flux RSS), vous résiliez votre
abonnement. On cesse alors de vous les livrer.
5. Tant que l’éditeur reste en activité, les particuliers, les hôtels, les
compagnies aériennes, etc., ne cessent de s’abonner et de se désabonner.
Nous appelons l’éditeur le Sujet ou l’objet Observable et les abonnés
des Observateurs
2 Solutions envisageables

• TIRER : Dans cette solution, une référence vers l’objet SUJET est mis à disposition de
chaque observateur.
• Les observateurs peuvent l’utiliser pour appeler une méthode getEtat() et ainsi
obtenir l’état de l’observable.
• Cette solution est nommée « TIRER» car c’est aux observateurs, une fois avertis de
l’évolution, d’aller chercher (TIRER ou PULL) l’information sur l’état.
• POUSSER : C’est la solution inverse on pousse l’etat vers les observateurs.
• on passe directement l’état actuel du SUJET dans une méthode en mode PUSH
("actualiser(TypeEtat)" , par exemple) de l’observateur.
• les observateurs disposent directement de l’état.
2ieme Exemple : API Moogle Météo
• On souhaite construire notre station météorologique consultable en ligne, à travers différents
moyen:
• Site web
• Application mobile
• Ou voir même des widgets qui peuvent être incorporés dans un portail d’entreprise

• La station sera basée sur un objet DonneesMeteo déjà existant, qui enregistre les conditions
météorologique à un moment donné (température, hygrométrie et pression
atmosphérique).
• L’ application fournira 3 affichages: conditions actuelles, statistiques et prévisions simples,
l’ensemble des 3 mesures sont mis à jour en temps réel au fur et à mesure que l’objet
DonneesMeteo acquiert les données les plus récentes.
• Cette station météo doit être extensible.On veut commercialiser une API pour que les autres
développeurs puissent réaliser leurs propres affichages et de les insérer directement.
Vue d’ensemble de l’application
• Les 3 composants du système sont:
• La station météo : Équipement physique qui recueille les données météo sur le temps.
• L’objet DonneesMeteo : qui mémorise les données provenant de la station et actualise l’affichage.
• L’affichage lui-même que les utilisateurs consultent pour connaître les conditions
météorologiques actuelles.

Capteur Extrait
d’humidité Les données Affiche
:DonneesMeteo Temp:22°
Capteur de Hygro :60
Station météo Pression :
température

Capteur de
pression Objet DonneesMeteo
Dispositif d’affichage

Ce que MétéoExpress Fournit Ce que nous implémentons


La classe métier DonneesMeteo est relativement
simple:

Ces trois méthodes retournent les mesures les plus récentes :


température, humidité, et pression atmosphérique.
DonneesMeteo
getTemperature()
Nous n’avons pas besoin de savoir comment ces variables sont
getHumidite() affectées; l’objet DonneesMeteo sait comment obtenir ces
getPression()
informations à jour.
actualiserMesures()

//Autres méthodes
/*
* Cette méthode est appelée chaque fois
* que les mesures ont été mises à jour
*/
public void actualiserMesures(){
// Votre code ici
}
• La classe DonneesMeteo a des méthodes d’accès pour trois valeurs de mesures:
• température,
• hygrométrie,
• pression atmosphérique.
• La méthode actualiserMesures() est appelée chaque fois qu’une nouvelle mesure est disponible.
On ne sait pas comment cette méthode est appelée
• On doit implémenter 3 affichages initiaux qui utilisent les données météorologiques:
• Affichage des conditions actuelles
• Affichage des statistiques
• Affichage des prévisions.
• Ces 3 affichages doivent être mis à jour, chaque fois que DonnesMeteo acquiert de nouvelles
données.
• Le système doit être extensible:
• D’autres développeurs pourrons créer d’autres affichages personnalisés
• Les utilisateurs pourront ajouter ou retirer autant d ’éléments qu’ils le souhaitaient à
l’application
Premier essai de station météo et critique
1iere proposition d’implémentation public class DonneesMeteo{
initiative d’un stagiaire //déclarations des variables d’instance
Le code ajouté à la méthode public void actualiserMesures(){
actualiderMesures() float t=getTemperature();
float h=getHumidite();
float p getPression();

affichageConditions.actualiser(t,h,p);
affichageStats.actualiser(t,h,p);
affichagePrevisions.actualiser(t,h,p);
}
// Autres méthodes
Rappel des Bonnes Pratiques }
• On doitcoder des interfaces, non des implémentations concrètes
• On ne doit pas modifier le code pour chaque nouvel élèment (d’affichage ds notre cas)
• On doit pouvoir ajouter (ou de supprimer) des éléments d’affichage dynamiquement
• On doit encapsuler les parties potentiellement variants
Analyse du code
Repensons à tous les concepts et les principes

public class DonneesMeteo{


//déclarations des variables d’instance
--En codant des implémentation public void actualiserMesures(){
concrètes, nous n’avons aucun float t=getTemperature();
float h=getHumidite();
moyen d’ajouter ni de supprimer
float p getPression();
des éléments sans modifier le
programme affichageConditions.actualiser(t,h,p);
affichageStats.actualiser(t,h,p);
affichagePrevisions.actualiser(t,h,p);
}
// Autres méthodes
}

++ nous semblons utiliser une interface commune pour --Points de variation : nous
communiquer avec les affichages.. Ils ont tous une devons l’encapsuler
méthode actualier() qui lie les valeurs de temp,
humidité et pression
Réflexion concernant Un Fonctionnement Général

Quand les données de l’objet sujet changent,


les observateurs en sont informés.

2 Objet Chien
Donée=2
2
2
Objet Sujet:
Objet Chat
Gère une donnée quelconque

Cet objet n’est pas un observateur


Objet Souris
:il n’est pas informés quand les
données du sujet changent
Les observateurs ont souscrit un abonnement ( se
Objet Vélo
sont enregistrés) au près du sujet pour recevoir
les mises à jour quand les données du sujet
changent. Ils peuvent eux-mêmes se désabonner.
Observateur ?
• C’est DP de la Catégorie : Comportement
• Il est Portée Objet
• Fortement utilisé et il est à la base du modèle MVC
• Définition :
◦ Le pattern observateur définit une relation entre les objets de
type un à plusieurs, de façon que, lorsqu’un objet change d’état,
tous ce qui en dépendent en soient informés et soient mis à jour
automatiquement
Diagramme de classe
Observable Observer
Explication
Le diagramme UML du pattern Observateur définit 2 interfaces et 2 classes.
• L’interface Observateur : implémentée par toutes classes qui souhaitent avoir le rôle
d’observateur.
• la classe ObservateurConcret implémente la méthode actualiser(Observable).
• actualiser(Observable) est appelée automatiquement lors d’un changement d’état de
l’observée.
• L’interface Observable qui devra être implémentée par les ObservableConcret.
• La classe ObservableConcret peut tenir informer ses observateurs à chaque changement
d’état. Elle possède en attribut :
• un tableau d’observateurs: liste des observateurs qui sont à l’écoute
• un état (ou plusieurs) : les observateurs désirent suivre l’évolution de ses valeurs
NB. Un observeteurConcret doit implémenter l’interface Observateur pour être à l’écoute,
il faut qu’il s’abonne à un Observable via la méthode ajouterObservateur(Observateur).
Et qu’il se désabonne quand il le désire
• La classe ObservableConcret dispose de 4 méthodes :
• ajouterObservateur(Observateur),
• supprimerObservateur(Observateur),
• notifierObservateurs()
• getEtat().
• Les 2 premières permettent, respectivement, d’ajouter des observateurs à
l’écoute de la classe et d’en suprimer.
• Les 2 dernières servent à notifier l’observateur du changement
• le pattern Observateur permet de lier dynamiquement (faire une liaison lors de
l’exécution du programme par opposition à lier statiquement à la compilation) des
observables à des observateurs.
• La méthode notifierObservateurs() est appelée lorsque l’état subit un changement
de valeur.
• Elle avertit tous les observateurs de cette mise à jour.

• La méthode getEtat() est un simple accesseur en lecture pour l’état.


• Les observateurs récupèrent via la méthode actualiser(Observable) un
pointeur vers l’objet observé.
• Grâce à ce pointeur, et à la méthode getEtat() il est possible d’obtenir la valeur
de l’état.
Chaque sujet peut
avoir plusieurs
Les objets utilise cette observateurs Tous les observateurs doivent
interface pour s’enregistrer implémenter cette interface.
comme observateur et pour Elle n’a qu’une seule méthode
résilier leur abonnement actualiser() qui est appelée
quand l’état du sujet change

sujet observateurs

Un sujet concret implémente


l’interface Sujet: 1 * Les observateurs concrets
• les méthodes d’ajout et de peuvent être n’importe quelle
suppression d’observateurs, classe qui implémente
• la méthode l’interface Observateur.
notifierObservateurs() sert à Chaque observateur
mettre à jour tous les s’enregistre au près du sujet
observateurs chaque fois que Le sujet concret peut
réel pour recevoir les mises à
l’état change. également avoir des jour;
méthodes pour accéder à
son état (getEtat()) et le
modifier (setEtat())
Un Faible couplage
• Lorsque 2 objets sont faiblement couplés, ils peuvent interagir sans pratiquement
se connaître.
• Le pattern observateur permet une conception dans laquelle le couplage entre sujet et
observateurs est faible:
• Le sujet ne sait qu’une seule chose :
• L’observateur implémente une certaine interface (Observateur).
• Il n’a pas donc besoin de connaître ni la classe concrète de l’observateur, ni ce qu’il fait
• Nous pouvons ajouter des observateurs à tout moment :
• Comme le sujet dépend uniquement d’une liste d’objets qui implémente l’interface
Observateur (observateurs:ArrayList), on peut ajouter, supprimer, modifier des
observateurs pendant l’exécution.
• Le sujet continu de fonctionner normalement
• Pas besoin de modifier le SUJET pour ajouter de nouveaux types d’observateurs :
• Si une nouvelle classe concrète se présente et a besoin d’être un observateur, nous
n’avons besoin d’ajouter RIEN au sujet pour gérer ce nouveau type.
• La nouvelle Classe doit implémente l’interface Observateur, et on l’enregistre entant que
observateur.
• Le sujet continue de diffuser des notifications à tous les observateurs sans même connaître
leurs TYPES CONCRETS.
• Nous pouvons réutiliser les observateurs et les sujets indépendamment les uns des
autres.
• Si nous avons un autre emploi d’un sujet ou d’un observateur, nous pouvons les réutiliser
sans problème par ce qu’ils sont faiblement couplés.
• Les modifications des sujets n’affectent pas les observateurs et inversement
Principe de conception

Il Faut Coupler faiblement les objets qui interagissent

Les conceptions faiblement couplées permettent de construire les systèmes OO souples,


capables de faire face aux changements par ce qu’ils minimisent l’interdépendance entre les
objets.
Conception de la station météo
Tous les affichages possèdent la méthode
Tous nos composants implémentent afficher(). Il implémentent donc cette
l’interface Observateur. Ainsi le sujet
Voici l’interface Sujet interface
dispose d’une interface à qui parler
quand le moment est venu.

observateurs

sujet

Ce composant Les développeurs peuvent


affiche les mesures développe leurs propres
courantes obtenues affichages
de l’objet
DonneesMeteo

DonneesMeteo implémente Cette classe affiche une prévision en


maintenant l’interface Sujet Cette classe Mémorise les fonction de l’indicateur du baromètre
mesures MIN, MOY et
MAX et les affiche.
Implémentation de la station meteo
public interface Sujet {
void enregisterObservateur(Observateur obs);
void supprimerObservateur(Observateur obs);
void notifierObservateurs();
}
public interface Observateur {
void actualiser(float t, float h, float p);

public interface Affichage {


void afficher();
}
Implémentation de l’interface sujet dans DonneesMeteo

import java.util.ArrayList;
public class DonneesMeteo implements Sujet {
private float temperature;
private float humidite;
private float pression;
private ArrayList observateurs;
public DonneesMeteo(){
observateurs=new ArrayList();
}
public void enregisterObservateur(Observateur obs) {
observateurs.add(obs);
}
public void supprimerObservateur(Observateur obs) {
int i=observateurs.indexOf(obs);
if(i>=0){
observateurs.remove(i);
}
}
public void notifierObservateurs() {
for(int i=0;i<observateurs.size();i++){
Observateur o=(Observateur)observateurs.get(i);
o.actualiser(temperature,humidite,pression);
}
}
public void setMesures(float t, float h, float p)
{
this.temperature=t;
this.humidite=h;
this.pression=p;
actualiserMesures();
}
public void actualiserMesures() {
notifierObservateurs();
}
}
Implémentation des affichages
public class AffichageConditions implements Observateur,
Affichage {
private float temperature;
private float humidite;
private Sujet donneesMeteo;
public AffichageConditions(Sujet dm){
this.donneesMeteo=dm;
donneesMeteo.enregisterObservateur(this);
}
public void afficher() {
System.out.println("Conditions actuelles:"+
temperature+" degès et "+humidite+" %d'hmidité");
}

public void actualiser(float t, float h, float p) {


this.temperature=t;
this.humidite=h;
afficher();
}
}
TestDonneesMeteo.java

dm:DonneesMeteo
public class TestDonneesMeteo {
temp=22
public static void main(String[] args) {
hum=65 ac:AffConditions
DonneesMeteo dm=new DonneesMeteo();
press=1020 temp=22
AffichageConditions ac=new AffichageConditions(dm);
O bservateurs: hum=65
dm.setMesures(22,65,1020);
sujet:
dm.setMesures(25,75,1000);
dm.setMesures(23,30,1800);
} aa:AutreAffichage
temp=22
press=1020
}
sujet:

Conditions actuelles:22.0 degès et 65.0 % d'hmidité


Conditions actuelles:25.0 degès et 75.0 % d'hmidité
Conditions actuelles:23.0 degès et 30.0 % d'hmidité
Le pattern Observateur de java
• Java le prend en charge nativement l’observateur dans plusieurs API.
• Le cas le plus général est constitué d’une interface Observer et d’une
classe Observable du package java.util.
Observable est une CLASSE,
Cette interface est la même
non une interface. Elle
dans le précédent
mémorise tous les observateurs
diagramme
et leurs envoie des
sauf que le nouveau nom de
notifications
la méthode actualiser() est
Sujet ou Observable concret. update()
enregistrer(), supprimer() et
notifier(), sont héritées de la
classe Observable.

l’interface Affichage est omise,


mais tous les affichages
continuent à l’implémenter.
Il y’aura quelques modification à
apporter à la méthode update()

Vous aimerez peut-être aussi