SlideShare une entreprise Scribd logo
1  sur  44
Télécharger pour lire hors ligne
DDeessiiggnn PPaatttteerrnnss 
PPaarrtt 22 
Mohamed Youssfi 
Laboratoire Signaux Systèmes Distribués et Intelligence Artificielle (SSDIA) 
ENSET, Université Hassan II Casablanca, Maroc 
Email : med@youssfi.net 
Supports de cours : http://fr.slideshare.net/mohamedyoussfi9 
Chaîne vidéo : http://youtube.com/mohamedYoussfi 
Recherche : http://www.researchgate.net/profile/Youssfi_Mohamed/publications 
med@youssfi.net
Le ppaatttteerrnn OObbsseerrvveerr :: 
TTeenneezz vvooss oobbjjeettss aauu ccoouurraanntt
DDeessiiggnn PPaatttteerrnnss dduu GGooFF ((GGaanngg ooff FFoouurr )) 
((GGaammmmaa,, HHeellmm,, JJoohhnnssoonn,, VVlliissssiiddeess)
PPaatttteerrnn OObbsseerrvvaatteeuurr 
CCCCaaaattttééééggggoooorrrriiiieeee : Comportement 
DDDDééééffffiiiinnnniiiittttiiiioooonnnn : 
◦ LLee ppaatttteerrnn oobbsseerrvvaatteeuurr ddééffiinniitt uunnee rreellaattiioonn 
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
DDiiaaggrraammmmee ddee ccllaassssee 
Observable Observer
IImmpplléémmeennttaattiioonn 
 Le diagramme UML du pattern Observateur définit deux interfaces et 
deux classes. 
◦ L’interface Observateur sera implémenté par toutes classes qui souhaitent 
avoir le rôle d’observateur. 
◦ C’est le cas de la classe ObservateurConcret qui implémente la méthode 
actualiser(Observable). Cette méthode sera appelée automatiquement lors d’un 
changement d’état de la classe observée. 
◦ On trouve également une interface Observable qui devra être 
implémentée par les classes désireuses de posséder des observateurs. 
◦ LLaa ccllaassssee OObbsseerrvvaabblleeCCoonnccrreett iimmpplléémmeennttee cceettttee iinntteerrffaaccee,, ccee qquuii lluuii 
permet de tenir informer ses observateurs. Celle-ci possède en attribut 
un état (ou plusieurs) et un tableau d’observateurs. L’état est un attribut 
dont les observateurs désirent suivre l’évolution de ses valeurs. Le 
tableau d’observateurs correspond à la liste des observateurs qui sont à 
l’écoute. 
◦ En effet, il ne suffit pas à une classe d’implémenter l’interface 
Observateur pour être à l’écoute, il faut qu’elle s’abonne à un 
Observable via la méthode ajouterObservateur(Observateur).
IImmpplléémmeennttaattiioonn 
 La classe ObservableConcret dispose de quatre méthodes : 
◦ ajouterObservateur(Observateur), 
◦ supprimerObservateur(Observateur), 
◦ notifierObservateurs() 
◦ getEtat(). 
 Les deux premières permettent, respectivement, d’ajouter des 
observateurs à l’écoute de la classe et d’en supprimer. 
 EEnn eeffffeett,, llee ppaatttteerrnn OObbsseerrvvaatteeuurr ppeerrmmeett ddee lliieerr ddyynnaammiiqquueemmeenntt ((ffaaiirree uunnee 
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. Celle-ci avertit tous les observateurs de cette mise 
à jour. 
 La méthode getEtat() est un simple accesseur en lecture pour l’état. En 
effet, les observateurs récupèrent via la méthode actualiser(Observable) 
un pointeur vers l’objet observé. Puis, grâce à ce pointeur, et à la méthode 
getEtat() il est possible d’obtenir la valeur de l’état.
IImmpplléémmeennttaattiioonn 
 Il existe une variation possible lors de l’utilisation de ce pattern. 
◦ TIRER : Dans la solution présentée, une référence vers l’objet 
observable est mis à disposition de chaque observateur. Ainsi les 
observateurs peuvent l’utiliser pour appeler la 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 l’information sur l’état. 
◦ POUSSER :Mais il existe la solution inverse appelée « POUSSER ». 
DDaannss ccee ccaass,, oonn ppaassssee ddiirreecctteemmeenntt ll’’ééttaatt aaccttuueell ddee ll’’oobbsseerrvvaabbllee ddaannss llaa 
méthode actualiser(TypeEtat). Ainsi les observateurs disposent 
directement de l’état. 
 Qu’elle est la meilleur solution entre les deux ? C’est la première parce 
qu’elle permet une fois de plus de lier faiblement l’observable à ses 
observateurs. En effet, si l’observateur dispose d’un pointeur vers l’objet 
observable et que la classe observable évolue en ajoutant un deuxième 
état. L’observateur souhaitant se tenir informé de ce deuxième état aura 
juste à appeler l’accesseur correspondant. Alors que si on « POUSSER » il 
faudrait changer la signature de la méthode ce qui peut s’avérer plus 
dommageable.
AApppplliiccaattiioonn
CCaahhiieerr ddeess cchhaarrggeess 
Félicitation! Votre société a été retenue pour construire notre station météorologique 
de dernière génération consultable en ligne! 
La station sera basée sur notre objet DonneesMeteo (brevet en cours),qui enregistre 
les conditions météorologique à un moment donné (température, hygrométrie et pression 
atmosphérique). 
Nous aimerions que vous nous créiez une application qui fournira d’abord trois 
affichages: conditions actuelles, statistiques et prévisions simples, tous trois mis à jour en 
temps réel au fur et à mesure que l’objet DonneesMeteo acquiert les données les plus récentes. 
DDee pplluuss cceettttee ssttaattiioonn mmééttééoo ddooiitt êêttrree eexxtteennssiibbllee.. MMééttééooEExxpprreessss vveeuutt ccoommmmeerrcciiaalliisseerr 
une API pour que les autres développeurs puissent réaliser leurs propres affichages et les insérer 
directement. Nous souhaitons que vous nous fournissiez cette API ! 
MétéoExpress est convaincu d’avoir un excellent modèle métier: une fois les clients 
acrochés, nous prévoyons de les facturer pour chaque affichage qu’ils utilisent. 
Le meilleur est pour la fin : vous serez payé en stock options. 
Nous attendons avec impatience vos documents de conception et votre première version alpha 
Cordialement, 
Jean-Loup Ragan, PDG MétéoExpress 
P.S. Nous vous envoyons par chrono les fichiers source de DonnesMeteo
Vue d’ensemble ddee ll’’aapppplliiccaattiioonn 
 Les trois 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. 
CCaapptteeuurr Extrait 
d’humidité 
Capteur de 
température 
Capteur de 
pression 
Station météo 
Les données 
Objet DonneesMeteo 
Temp: 22° 
Hygro : 60 
Pression : 
Dispositif a’affichage 
Affiche 
:DonneesMeteo 
Ce que MétéoExpress Fournit Ce que nous implémentons 
Si nous choisissons de l’accepter, notre tâche consiste à créer une application qui 
utilise l’objet DonneesMeteo qui actualise ces trois affichages: conditions actuelles, 
statistiques et prévisions
A l’intérieur de la classe DDoonnnneeeessMMeetteeoo 
 Le lendemain matin, les fichiers source de DonneesMeteo 
arrivent comme promis. 
 Nous jetons un coup d’oeil au code qui semble relativement 
simple: 
DonneesMeteo 
Ces trois méthodes retournent les mesures les plus récentes : 
température, humidité, et pression atmosphérique. 
getTemperature() 
getHumidite() 
getPression() 
actualiserMesures() 
//Autres méthodes 
Nous n’avons pas besoin de savoir comment ces variables sont 
affectées; l’objet DonneesMeteo sait comment obtenir ces 
informations à jour. 
/* 
* Cette méthode est appelée chaque fois 
* que les mesures ont été mises à jour 
*/ 
public void actualiserMesures(){ 
// Votre code ici 
}
RRééccaappiittuulloonnss…….. 
 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. Nous ne savons pas comment cette méthode est appelée, et peu 
importe. 
 Nous devrons implémenter trois affichages qui utilisent les données 
météorologiques: 
◦ Un affichage des conditions actuelles 
◦ Un affichage des statistiques 
◦ UUnn aaffffiicchhaaggee ddeess pprréévviissiioonnss.. 
 Ces trois affichages doivent être mis à jour, chaque fois que DonnesMeteo aquiert 
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 
◦ Actuellement, nous ne connaissons que les trois types d’affichages initiaux 
 Conditions actuelles 
 Statistiques 
 prévisions
Premier essai ddee ssttaattiioonn mmééttééoo 
 Voici une première possibilité d’implémentation: nous suivons l’indication des 
développeurs de MeteoExpress et nous ajoutons notre code à la méthode 
actualiderMesures(): 
public class DonneesMeteo{ 
//déclarations des variables d’instance 
public void actualiserMesures(){ 
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 
} 
AAAA vvvvoooossss ccccrrrraaaayyyyoooonnnnssss 
D’après notre première implémentation, quels énoncés suivants sont vrais? 
 A. Nous codons des implémentations concrètes, non des interfaces 
 B. Nous devons modifier le code pour chaque nouvel élément d’affichage 
 C. Nous n’avons aucun moyen d’ajouter (ou de supprimer) des éléments d’affichage dynamiquement 
 D. Les éléments d’affichage n’implémentent pas une interface commune 
 E. Nous n’avons pas encapsulé les parties qui varient 
 F. Nous violons l’encapsulation de la classe DonneesMeteo
Qu’est ce qui cloche dans notre iimmpplléémmeennttaattiioonn 
 Repenser à tous les concepts et les principes du chapitre 
précédent. 
public class DonneesMeteo{ 
//déclarations des variables d’instance 
public void actualiserMesures(){ 
float t=getTemperature(); 
float h=getHumidite(); 
float p getPression(); 
En codant des implémentation 
concrètes, nous n’avons aucun 
moyen d’ajouter ni de supprimer des 
affichageConditions.actualiser(t,h,p); 
affichageStats.actualiser(t,h,p); 
affichagePrevisions.actualiser(t,h,p); 
} 
// Autres méthodes 
} 
éléments sans modifier le 
programme 
Au moins, nous semblons utiliser une interface commune pour 
communiquer avec les affichages.. Ils ont tous une méthode 
actualier() qui lie les valeurs de temp, humidité et pression 
Points de variation : nous devons 
l’encapsuler
Faites connaissance avec le ppaatttteerrnn OObbsseerrvvaatteeuurr 
 Vous savez comment fonctionne un abonnement à un 
magazine: 
1. Un éditeur se lance dans les affaires et commence à diffuser des 
magazines 
2. vous souscrivez un abonnement 
3. Chaque fois qu’il y’a une nouvelle édition, vous la recevez. Et tant 
que vous êtes abonné, vous recevez les nouvelles éditions. 
4. Quand vous ne vouliez pas de ces magazines, 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. 
 Si vous avez compris cet exemple, vous avez compris 
l’essentiel du patterns Observateur, sauf que nous appelons 
l’éditeur le SUJET et les abonnés les OBSERVATEURS
Faites connaissance avec le ppaatttteerrnn OObbsseerrvvaatteeuurr 
 Regardons de plus près 
Quand les données de l’objet sujet 
changent, les observateurs en sont 
informés. 
Donée=2 
2 Objet Chien 
2 
Objet Sujet: 
Gère une donnée quelconque 
Objet Chat 
Objet Souris 
2 
Objet Canard 
Cet objet n’est pas un observateur 
: il n’est pas informés quand les 
données du sujet changent Les observateurs ont souscrit un abonnement ( se 
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.
Pattern Observateur :: ddééffiinniittiioonn 
Le pattern observateur définit une 
relation entre les objets de type un à 
pplluussiieeuurrss,, ddee ffaaççoonn qquuee,, lloorrssqquu’’uunn oobbjjeett 
change d’état, tous ce qui en dépendent 
en soient informés et soient mis à jour 
automatiquement
Pattern Observateur : Diagramme ddee ccllaasssseess 
sujet 
Voici l’interface Sujet les 
objets utilise cette 
interface pour s’enregistrer 
comme observateur et 
pour résilier leur 
abonnement 
Tous les observateurs 
potentiels doivent 
implémenter l’interface 
Observateur. 
Cette interface n’a qu’une 
seule méthode actualiser() 
qui est appelée quand l’état 
du sujet change 
Chaque sujet peut avoir 
plusieurs observateurs 
observateurs 
Le sujet concret peut 
également avoir des 
méthodes pour accéder à 
son état (getEtat()) et le 
modifier (setEtat()) 
Un sujet concret implémente 
toujours l’interface Sujet. 
Outre les méthode d’ajout et 
de suppression 
d’observateurs, le sujet 
concret implémente la 
méthode 
notifierObservateurs() qui 
sert à mettre à jour tous les 
observateurs chaque fois que 
l’état change. 
Les observateurs 
concrets peuvent être 
n’importe quelle classe 
qui implémente l’interface 
Observateur. 
Chaque observateur 
s’enregistre au près du 
sujet réel pour recevoir 
les mises à jour; 
1 *
Le ppoouuvvooiirr dduu ffaaiibbllee ccoouuppllaaggee 
 Lorsque deux 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 ni quoi que 
ce soit d’autre. 
◦ Nous pouvons ajouter des observateurs à tout moment : 
 CCoommmmee llee ssuujjeett ddééppeenndd uunniiqquueemmeenntt dd’’uunnee lliissttee dd’’oobbjjeettss qquuii iimmpplléémmeennttee ll’’iinntteerrffaaccee OObbsseerrvvaatteeuurr 
(observateurs:ArrayList), nous pouvons ajouter, supprimer, modifier des observateurs à volonté 
pendant l’exécution. 
 Le sujet continue de fonctionner comme si rien n’était 
◦ Nous n’avons jamais besoin de modifier le sujet pour ajouter de nouveaux 
types d’observateurs : 
 Disons qu’une nouvelle classe concrète se présente et a besoin d’être un observateur, nous 
n’avons besoin d’ajouter quoi que ce soit au sujet pour gérer ce nouveau type. 
 Il suffit qu’elle implémente l’interface Observateur, et de l’enregistrer entant que observateur. 
 Le sujet continue de diffuser des notifications à tous les observateurs. 
◦ 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
Le ppoouuvvooiirr dduu ffaaiibbllee ccoouuppllaaggee 
Principe de conception: 
Efforcez-vous à coupler faiblement les 
objets qui interagissent 
4er Principe de conception 
Les conceptions faiblement couplées nous 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.
AA vvooss ccrraayyoonnss 
 Avant de continuer, essayer d’esquisser 
les classes et les interfaces nécessaires 
pour implémenter la station météo, 
notamment la classe DonneesMeteo et 
lleess ccllaasssseess ddeess ddiifffféérreennttss aaffffiicchhaaggeess.. 
◦ S’il vous faut un peu d’aide, lisez la page 
suivante : vos collègues sont déjà entrain de 
penser à la conception de la station météo.
CCoonnvveerrssaattiioonn ddaannss uunn bbooxx 
 Marie: Et bien, ça aide de savoir que nous utilisons le pattern Observateur. 
 Anne: Oui… mais comment allons nous l’appliquer. 
 Marie : regardons à nouveau la 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 
 Marie : ça a l’air claire quand on y pense : Notre classe DonneesMeteo est le « un », 
et le « plusieurs », ce sont les éléments qui affichent les différentes mesures; 
 Anne : c’est vrai, la classe DonneesMeteo a avidement un état… la température, 
l’humidité, la pression atmosphérique, et bien sûr, ces données changent. 
 Marie : Oui, et quand ces données changent, il faut notifier les éléments d’affichage 
pour qu’ils puissent mettre à jour l’affichage en utilisant les nouvelles mesures. 
 Anne : super, maintenant je crois que je vois comment appliquer le pattern 
Observateur à notre problème. 
 Marie : mais il y’a encore deux ou trois choses que je ne suis pas sûre d’avoir 
comprises. 
 Anne : Pae exemple ? 
 Marie : D’abord, comment faire pour que les éléments d’affichage puissent obtenir 
les mesures.
CCoonnvveerrssaattiioonn ddaannss uunn bbooxx 
 Anne: Eh bien, en regardant à nouveau le diagramme de classes du pattern 
Observateur, si nous faisons de l’objet DonneesMeteo le sujet et des éléments 
d’affichage les observateurs, alors les affichages vont s’enregistrer eux-mêmes 
auprès de l’objet DonneesMeteo pour obtenir les informations dont ils 
auront besoin, non ? 
 Marie: Oui… et une fois que la station météo est au courant de l’existence 
d’un élément d’affichage, elle peut simplement appeler une méthode pour lui 
transmettre les mesures. 
 Anne: Il faut se souvenir que chaque affichage peut être différent… et c’est 
là que je crois que qu’intervient une interface commune. Même si, chaque 
composant est d’un type différent, ils doivent implémenter tous une même 
interface pour que l’objet DonneesMeteo sache comment leur transmettre les 
mesures. 
 Marie: je vois ce que tu veux dire. Chaque affichage aura par exemple une 
méthode actualier() que DonneesMeteo va appeler. 
 Anne: Et actualiser() est définie dans une inteface commune que tous les 
éléments d’affichage implémenteront.
Concevoir llaa ssttaattiioonn mmééttééoo 
Voici l’interface Sujet 
Tous nos composants implémentent 
l’interface Observateur. Ainsi le 
sujet dispose d’une interface à qui 
parler quand le moment est venu. 
Tous les affichages possèdent 
la méthode afficher(). Il 
implémentent donc cette 
interface 
observateurs 
sujet 
Ce composant 
affiche les mesures 
courantes obtenues 
de l’objet 
DonneesMeteo 
Cette classe Mémorise les 
mesures MIN, MOY et 
MAX et les affiche. 
Les développeurs 
peuvent développer 
leurs propres 
affichages 
Cette classe affiche une 
prévision en fonction de 
l’indicateur du baromètre 
DonneesMeteo implémente 
maintenant l’interface Sujet
Implémenter llaa ssttaattiioonn mmeetteeoo 
 Commençons par les interfaces 
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émenter l’interface sujet ddaannss DDoonnnneeeessMMeetteeoo 
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); 
} 
}
Implémenter l’interface sujet dans DDoonnnneeeessMMeetteeoo ((ssuuiittee)) 
public void notifierObservateurs() { 
for(int i=0;iobservateurs.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(); 
} 
}
IImmpplléémmeenntteerr lleess aaffffiicchhaaggeess 
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(); 
} 
}
Mettre en route llaa ssttaattiioonn mmééttééoo 
TTeessttDDoonnnneeeessMMeetteeoo..jjaavvaa 
public class TestDonneesMeteo { 
public static void main(String[] args) { 
DonneesMeteo dm=new DonneesMeteo(); 
AffichageConditions ac=new AffichageConditions(dm); 
dm.setMesures(22,65,1020); 
dm:DonneesMeteo 
temp=22 
hum=65 
press=1020 
Observateurs: 
ac:AffConditions 
temp=22 
hum=65 
dm.setMesures(25,75,1000); 
dm.setMesures(23,30,1800); 
} 
} 
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é 
sujet: 
aa:AutreAffichage 
temp=22 
press=1020 
sujet:
Utiliser le pattern OObbsseerrvvaatteeuurr ddee jjaavvaa 
 Jusqu’ici, nous avons écrit notre propre code pour appliquer le pattern Observateur,mais 
java le prend en charge nativement dans plusieurs de ses API. 
 Le cas le plus général est constitué d’une interface Observer et d’une classe Observable 
du package java.util. 
 Elles sont très similaires à nos interfaces, mais elles apportent d’autres fonctionnalités 
« toutes prêtes ». 
Observable est une CLASSE, 
non une interface. Elle 
mémorise tous les 
observateurs et leurs envoie 
des notifications à votre place 
Cette interface devrait vous sembler 
familière. En effet, c’est la même que 
dans notre précédent diagramme de 
classes sauf que le nom de la méthode 
actualiser() est devenu update(). 
Voici notre Sujet que nous 
pouvons maintenant appeler 
l’Observable. Nous n’avons 
plus besoin d’implémenter les 
méthode enregistrer(), 
supprimer() et notifier(), car 
Nous avons omis l’interface 
Affichage, mais tous les 
affichages continuent à 
l’implémenter. 
Il y’aura quelques 
modification à apporter à la 
méthode update() 
nous avons hériter ce 
comportement de la classe 
Observable.
Comment fonctionne le pattern OObbsseerrvvaatteeuurr eenn jjaavvaa 
 Le pattern Observateur intégré à java fonctionne un peu 
différemment de l’implémentation que nous avons choisie 
pour notre première station météo. 
 La différence la plus évidente réside dans le faite que 
DonneesMeteo (notre sujet) étend maintenant la classe 
Observable et nous héritons (entre autres) des méthodes 
addObserver(), deleteObserver() et notifierObservers(). Voici 
comment nous utilisons la version java de cet Observateur: 
◦ Pour qu’un objet devient observateur… 
 Comme d’habitude, implémenter l’interface Observer et appeler la méthode 
addObserver() de l’objet Observable. 
 De même pour supprimer un observateur, il suffit d’appeler la méthode 
deleteObserver().
Comment fonctionne le pattern OObbsseerrvvaatteeuurr eenn jjaavvaa 
◦ Pour que l’observable envoie des notifications… 
 Tout d’abord, il faut qu’il devienne Observable en étendant la super classe 
java.util.Observable. Puis l’on possède à deux étapes: 
 Vous devez d’abord appeler la méthode setChanged(), pour signifier que l ’état de votre 
objet à changé 
 Puis vous appelez l’une des deux méthodes notifyObservers(): 
 public void notifyObservers() : méthode dans argument 
 notifyObservers(Object arg) : méthode avec argument arg de type Object 
◦ Pour qu’un observateur reçoive des notifications… 
Il implémente la méthode update comme auparavant, mais sa signature est diffère 
 légèrement: 
 Public void update(Observer o, Object arg ): 
 Le premier paramètre représente le sujet qui envoyé la notification 
 Le deuxième paramètre représente l’objet qui contient les données transmises à 
notifyObservers ou null si aucun objet n’a été spécifié. 
 Si vous voulez pousser des données vers des observateurs, vous pouvez les transmettre 
sous forme d’objet donnée à la méthode notifyObservers(Object arg). 
 Si non, l’observateur doit tirer les données de l’objet Observable qui lui a été transmis. 
◦ Voyons comment faire tout cela dans notre station météo.
MMéétthhooddee sseettCChhaannggeedd(()) 
◦ Avant de commencer, on peut remarquer l’existence 
inhabituelle de la méthode setChanged() dans la classe 
Observable. 
◦ A quoi sert donc cette méthode? 
◦ RRééppoonnssee:: 
 Cette méthode sert à signifier que l’état a changé et que 
notifyObservers(), quand elle est appelée, doit mettre à jour les 
observateurs. 
 Si notifyObservers() est appelée sans qu’on ait d’abord appelé 
setChanged(), les observateurs ne seront pas notifiés. 
 Jetons un coup d’oeil dans les coulisses de la classe Observable pour 
voir comment cala fonctionne.
CCoouulliisssseess ddee OObbssaarrvvaallee 
protected void setChanged() { 
changed = true; } 
protected void clearChanged() { 
changed = false; } 
public void notifyObservers() { 
notifyObservers(null); } 
La méthode setChanged positionne un 
drapeau changed à true. 
La méthode clearChanged positionne 
le drapeau changed à false. 
public void notifyObservers(Object arg) { 
Object[] obsArr; 
if (!changed) return; 
obsArr = obs.toArray(); 
clearChanged(); 
for (int i = obsArr.length-1; i=0; i--){ 
Observer o=(Observer) obsArr[i]; 
o.update(this, arg); 
} 
} 
notifyObservers() ne notifie les 
observateurs que si la valeur du 
drapeau est true; 
Si le drapeau changed est true, elle le 
remet à false et puis notifie les 
observateurs
Intérêt dduu ddrraappeeaauu cchhaannggeedd 
 La méthode setChanged() est conçue pour vous autoriser plus de souplesse dans 
la façon dont vous mettez à jour les observateurs en vous permettant d’optimiser 
les notifications. 
 Par exemple, 
◦ Dans le cas de notre station météo, imaginez que les capteurs de mesures soient si 
sensibles que les températures affichées varient constamment de quelques dixième de 
degrés. 
◦ LL’’oobbjjeett DDoonnnneeeessMMeetteeoo ppoouurrrraaiieenntt éémmeettttrree ddeess nnoottiiffiiccaattiioonn eenn ppeerrmmaanneennccee.. 
◦ Mais si nous voulions émettre des notifications toutes moins fréquentes, nous n’appelons 
setChanged() que lorsque la température aura augmentée ou diminuée d’un demi degré. 
 Vous n’utiliserez, peut-être pas très souvent cette fonctionnalité, mais sachez 
qu’elle existe en cas de besoin. 
 Dans tous les cas, vous devez appeler la méthode setChanged() pour que les 
notifications soient effectuées. 
 Comme vous pouvez également appeler clearChanged(), réinitialise le drapeau 
« changed » à false et la méthode hasChanged() qui retourne la valeur du 
drapeau.
Retravailler la station météo avec llee ppaatttteerrnn OObbsseerrvveerr dduu 
ppaacckkaaggee jjaavvaa..uuttiill 
DDoonnnneeeessMMeetteeoo..jjaavvaa 
import java.util.Observable; 
public class DonneesMeteo extends Observable { 
private float temperature; 
private float humidite; 
private float pression; 
public DonneesMeteo(){} 
public float getHumidite() { 
return humidite; 
} 
public void actualiserMesures(){ 
setChanged(); 
notifyObservers(); 
}
Retravailler la station météo avec llee ppaatttteerrnn OObbsseerrvveerr 
dduu ppaacckkaaggee jjaavvaa..uuttiill 
DDoonnnneeeessMMeetteeoo..jjaavvaa ((ssuuiittee)) 
public void setMesures(float t, float h, float p) { 
this.temperature=t; 
this.humidite=h; 
this.pression=p; 
actualiserMesures(); 
} 
public float getPression() { 
return pression; 
} 
public float getTemperature() { 
return temperature; 
} 
}
AffichageConditions.jjaavvaa ((ssuuiittee)) 
import java.util.Observable; 
import java.util.Observer; 
public class AffichageConditions implements Observer,Affichage { 
Observable sujet; 
private float temperature; 
private float humidite; 
public AffichageConditions(Observable obs){ 
this.sujet=obs; 
sujet.addObserver(this); 
} 
public void update(Observable obs, Object arg) { 
if(obs instanceof DonneesMeteo){ 
DonneesMeteo dm=(DonneesMeteo)obs; 
this.temperature=dm.getTemperature(); 
this.humidite=dm.getHumidite(); 
afficher(); 
} 
} 
public void afficher() { 
System.out.println(Conditions actuelles:+ 
temperature+ degès et +humidite+ % d'hmidité); 
} 
}
TTrraavvaaiill àà ffaaiirree 
 Ecrire une implémentation de 
AffichagePrevisions de façon à afficher les 
messages suivants: 
◦ « AAmméélliioorraattiioonn eenn ccoouurrss » ssii llaa ddiifffféérreennccee ddee pprreessssiioonn 
est positive 
◦ « le temps se rafraîchit », si la différence de pression 
est négative. 
◦ « Dépression bien installée », si la pression ne change 
pas.
Autres endroits ou se trouve llee ppaatttteerrnn oobbsseerrvvaatteeuurr 
ddaannss llee JJDDKK.. 
 Le composant Swing JButton est un sujet qui hérite de la 
classe AbstractButton. Si vous regarder la structure de cette 
classe vous regardez des méthodes comme add et remove qui 
permettent d’ajouter et de supprimer des observateurs qu’on 
appelle dans la terminologie de Swing des listenners 
(Auditeurs). 
 Ces listeners sont à l’écoute des différents types 
d’événements qui peuvent se produire dans le composant 
JButton. 
 Par exemple un ActionListener vous permet d’acouter tous 
les types d’actions qui peuvent être appliquées à un bouton, 
comme les clics. 
 Si l’un des événements se produit sur le bouton, ce dernier 
notifie tous les observateurs qui sont de type ActionListener 
en faisant appel à la méthode actionPerformed() de chaque 
ActionListener.
EExxeemmppllee ppoouurr llee ppllaaiissiirr 
AbstractButon 
JButton 
ActionListener 
actionPerformed() 
AuditeurAnge 
actionPerformed() 
AuditeurDemon 
actionPerformed() 
Console: 
 Créer un JFrame 
 Créer un JButton : Sujet 
 Créer deux listeners ange et demon : Observateurs 
 enregistrer les deux listeners chez le bouton en faisant 
appel à la méthode addActionListener() 
 Si un utilisateur clique sur le bouton, son état change et 
tous les observateurs sont notifiés en exécutant leurs 
méthodes actionPerformed() 
Fais le tu as tout à gagner! 
Ne le fais pas, tu pourrais le regréter
EExxeemmppllee 
ExObsSwing.java: 
import java.awt.*; 
import java.awt.event.*; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
public class ExObsSwing{ 
private JFrame jf; 
private JButton bouton; 
// Créer un premier observateur qui implémente ActionListener 
class AutiteurAnge implements ActionListener{ 
public void actionPerformed(ActionEvent e) { 
System.out.println(Ne le fais pas, tu pourrais le regréter); 
} 
} 
// Créer un deuxième observateur qui implémente ActionListener 
class AutiteurDemon implements ActionListener{ 
public void actionPerformed(ActionEvent e) { 
System.out.println(Fais le tu as tout à gagner!); 
} 
}
EExxeemmppllee 
public void go(){ 
jf=new JFrame(); 
// Créer le sujet 
bouton=new JButton(Dois-je le faire); 
// Créer deux observateurs ange et demon 
AuditeurAnge ange=new AuditeurAnge(); 
AuditeurDemon demon=new AuditeurDemon(); 
// Enregistrer les deux observateurs chez le bouton 
bouton.addActionListener(ange); 
bouton.addActionListener(demon); 
jf.getContentPane().setLayout(new FlowLayout()); 
jf.getContentPane().add(bouton); 
jf.setBounds(100,100,400,400); 
jf.show(); 
// Le bouton s’affiche dans la frame. 
// En cliquant sur celui-ci, tous les listeners enregistrés 
// chez le boutons sont notifiés et exécutent la méthode 
// actionPerformed(); équivalent à update() 
} 
public static void main(String[] args) { 
ExObsSwing ex=new ExObsSwing(); 
ex.go(); 
} 
}

Contenu connexe

Tendances

Java entreprise edition et industrialisation du génie logiciel par m.youssfi
Java entreprise edition et industrialisation du génie logiciel par m.youssfiJava entreprise edition et industrialisation du génie logiciel par m.youssfi
Java entreprise edition et industrialisation du génie logiciel par m.youssfiENSET, Université Hassan II Casablanca
 
Support de cours EJB 3 version complète Par Mr Youssfi, ENSET, Université Ha...
Support de cours EJB 3 version complète Par Mr  Youssfi, ENSET, Université Ha...Support de cours EJB 3 version complète Par Mr  Youssfi, ENSET, Université Ha...
Support de cours EJB 3 version complète Par Mr Youssfi, ENSET, Université Ha...ENSET, Université Hassan II Casablanca
 
Mohamed youssfi support architectures logicielles distribuées basées sue les ...
Mohamed youssfi support architectures logicielles distribuées basées sue les ...Mohamed youssfi support architectures logicielles distribuées basées sue les ...
Mohamed youssfi support architectures logicielles distribuées basées sue les ...ENSET, Université Hassan II Casablanca
 
Rapport j2ee: Gestion d’un compte bancaire En utilisant les EJB 3.0
Rapport j2ee: Gestion d’un compte bancaire En utilisant les EJB 3.0Rapport j2ee: Gestion d’un compte bancaire En utilisant les EJB 3.0
Rapport j2ee: Gestion d’un compte bancaire En utilisant les EJB 3.0Ayoub Rouzi
 

Tendances (20)

Support de cours Spring M.youssfi
Support de cours Spring  M.youssfiSupport de cours Spring  M.youssfi
Support de cours Spring M.youssfi
 
Support programmation orientée aspect mohamed youssfi (aop)
Support programmation orientée aspect mohamed youssfi (aop)Support programmation orientée aspect mohamed youssfi (aop)
Support programmation orientée aspect mohamed youssfi (aop)
 
Cours design pattern m youssfi partie 5 adapter
Cours design pattern m youssfi partie 5 adapterCours design pattern m youssfi partie 5 adapter
Cours design pattern m youssfi partie 5 adapter
 
Site JEE de ECommerce Basé sur Spring IOC MVC Security JPA Hibernate
Site JEE de ECommerce  Basé sur Spring IOC MVC Security JPA HibernateSite JEE de ECommerce  Basé sur Spring IOC MVC Security JPA Hibernate
Site JEE de ECommerce Basé sur Spring IOC MVC Security JPA Hibernate
 
Support de cours technologie et application m.youssfi
Support de cours technologie et application m.youssfiSupport de cours technologie et application m.youssfi
Support de cours technologie et application m.youssfi
 
Support JEE Spring Inversion de Controle IOC et Spring MVC
Support JEE Spring Inversion de Controle IOC et Spring MVCSupport JEE Spring Inversion de Controle IOC et Spring MVC
Support JEE Spring Inversion de Controle IOC et Spring MVC
 
Support de cours entrepise java beans ejb m.youssfi
Support de cours entrepise java beans ejb m.youssfiSupport de cours entrepise java beans ejb m.youssfi
Support de cours entrepise java beans ejb m.youssfi
 
Support JEE Servlet Jsp MVC M.Youssfi
Support JEE Servlet Jsp MVC M.YoussfiSupport JEE Servlet Jsp MVC M.Youssfi
Support JEE Servlet Jsp MVC M.Youssfi
 
Support developpement applications mobiles avec ionic v3 et v4
Support developpement applications mobiles avec ionic v3 et v4Support developpement applications mobiles avec ionic v3 et v4
Support developpement applications mobiles avec ionic v3 et v4
 
Support NodeJS avec TypeScript Express MongoDB
Support NodeJS avec TypeScript Express MongoDBSupport NodeJS avec TypeScript Express MongoDB
Support NodeJS avec TypeScript Express MongoDB
 
Support POO Java Deuxième Partie
Support POO Java Deuxième PartieSupport POO Java Deuxième Partie
Support POO Java Deuxième Partie
 
Java entreprise edition et industrialisation du génie logiciel par m.youssfi
Java entreprise edition et industrialisation du génie logiciel par m.youssfiJava entreprise edition et industrialisation du génie logiciel par m.youssfi
Java entreprise edition et industrialisation du génie logiciel par m.youssfi
 
Gestion comptes bancaires Spring boot
Gestion comptes bancaires Spring bootGestion comptes bancaires Spring boot
Gestion comptes bancaires Spring boot
 
Support POO Java première partie
Support POO Java première partieSupport POO Java première partie
Support POO Java première partie
 
Sécurité des Applications Web avec Json Web Token (JWT)
Sécurité des Applications Web avec Json Web Token (JWT)Sécurité des Applications Web avec Json Web Token (JWT)
Sécurité des Applications Web avec Json Web Token (JWT)
 
Support de cours EJB 3 version complète Par Mr Youssfi, ENSET, Université Ha...
Support de cours EJB 3 version complète Par Mr  Youssfi, ENSET, Université Ha...Support de cours EJB 3 version complète Par Mr  Youssfi, ENSET, Université Ha...
Support de cours EJB 3 version complète Par Mr Youssfi, ENSET, Université Ha...
 
Mohamed youssfi support architectures logicielles distribuées basées sue les ...
Mohamed youssfi support architectures logicielles distribuées basées sue les ...Mohamed youssfi support architectures logicielles distribuées basées sue les ...
Mohamed youssfi support architectures logicielles distribuées basées sue les ...
 
Polymorphisme, interface et classe abstraite
Polymorphisme, interface et classe abstraitePolymorphisme, interface et classe abstraite
Polymorphisme, interface et classe abstraite
 
Traitement distribue en BIg Data - KAFKA Broker and Kafka Streams
Traitement distribue en BIg Data - KAFKA Broker and Kafka StreamsTraitement distribue en BIg Data - KAFKA Broker and Kafka Streams
Traitement distribue en BIg Data - KAFKA Broker and Kafka Streams
 
Rapport j2ee: Gestion d’un compte bancaire En utilisant les EJB 3.0
Rapport j2ee: Gestion d’un compte bancaire En utilisant les EJB 3.0Rapport j2ee: Gestion d’un compte bancaire En utilisant les EJB 3.0
Rapport j2ee: Gestion d’un compte bancaire En utilisant les EJB 3.0
 

Similaire à Cours design pattern m youssfi partie 2 observer

Programmation Android 07 - Techniques avancées
Programmation Android 07 - Techniques avancéesProgrammation Android 07 - Techniques avancées
Programmation Android 07 - Techniques avancéesYann Caron
 
Android Lab Test : Le capteur gyroscope (français)
Android Lab Test : Le capteur gyroscope (français)Android Lab Test : Le capteur gyroscope (français)
Android Lab Test : Le capteur gyroscope (français)Bruno Delb
 
Windows Phone Workshop sensors and battery
Windows Phone Workshop sensors and batteryWindows Phone Workshop sensors and battery
Windows Phone Workshop sensors and batteryZayen Chagra
 
Chap XII Analyse Numerique
Chap XII Analyse NumeriqueChap XII Analyse Numerique
Chap XII Analyse NumeriqueMohammed TAMALI
 
In01 - Programmation Android - 07 - techniques avancées
In01 - Programmation Android - 07 - techniques avancéesIn01 - Programmation Android - 07 - techniques avancées
In01 - Programmation Android - 07 - techniques avancéesYann Caron
 
Cours climat consultant 6.0 et meteonorm 7
Cours climat consultant 6.0 et meteonorm 7Cours climat consultant 6.0 et meteonorm 7
Cours climat consultant 6.0 et meteonorm 7Cherif Ben Bacha
 

Similaire à Cours design pattern m youssfi partie 2 observer (8)

Programmation Android 07 - Techniques avancées
Programmation Android 07 - Techniques avancéesProgrammation Android 07 - Techniques avancées
Programmation Android 07 - Techniques avancées
 
Patron observer
Patron observerPatron observer
Patron observer
 
Android Lab Test : Le capteur gyroscope (français)
Android Lab Test : Le capteur gyroscope (français)Android Lab Test : Le capteur gyroscope (français)
Android Lab Test : Le capteur gyroscope (français)
 
Windows Phone Workshop sensors and battery
Windows Phone Workshop sensors and batteryWindows Phone Workshop sensors and battery
Windows Phone Workshop sensors and battery
 
Chap XII Analyse Numerique
Chap XII Analyse NumeriqueChap XII Analyse Numerique
Chap XII Analyse Numerique
 
In01 - Programmation Android - 07 - techniques avancées
In01 - Programmation Android - 07 - techniques avancéesIn01 - Programmation Android - 07 - techniques avancées
In01 - Programmation Android - 07 - techniques avancées
 
TP_1.pdf
TP_1.pdfTP_1.pdf
TP_1.pdf
 
Cours climat consultant 6.0 et meteonorm 7
Cours climat consultant 6.0 et meteonorm 7Cours climat consultant 6.0 et meteonorm 7
Cours climat consultant 6.0 et meteonorm 7
 

Plus de ENSET, Université Hassan II Casablanca

Mise en oeuvre des Frameworks de Machines et Deep Learning pour les Applicati...
Mise en oeuvre des Frameworks de Machines et Deep Learning pour les Applicati...Mise en oeuvre des Frameworks de Machines et Deep Learning pour les Applicati...
Mise en oeuvre des Frameworks de Machines et Deep Learning pour les Applicati...ENSET, Université Hassan II Casablanca
 
Conférence: Catalyseurs de l'Intelligence Artificielle et Écosystème des Fram...
Conférence: Catalyseurs de l'Intelligence Artificielle et Écosystème des Fram...Conférence: Catalyseurs de l'Intelligence Artificielle et Écosystème des Fram...
Conférence: Catalyseurs de l'Intelligence Artificielle et Écosystème des Fram...ENSET, Université Hassan II Casablanca
 
Architecture jee principe de inversion de controle et injection des dependances
Architecture jee principe de inversion de controle et injection des dependancesArchitecture jee principe de inversion de controle et injection des dependances
Architecture jee principe de inversion de controle et injection des dependancesENSET, Université Hassan II Casablanca
 
Développement d'un site web jee de e commerce basé sur spring (m.youssfi)
Développement d'un site web jee de e commerce basé sur spring (m.youssfi)Développement d'un site web jee de e commerce basé sur spring (m.youssfi)
Développement d'un site web jee de e commerce basé sur spring (m.youssfi)ENSET, Université Hassan II Casablanca
 
Systèmes multi agents concepts et mise en oeuvre avec le middleware jade
Systèmes multi agents concepts et mise en oeuvre avec le middleware jadeSystèmes multi agents concepts et mise en oeuvre avec le middleware jade
Systèmes multi agents concepts et mise en oeuvre avec le middleware jadeENSET, Université Hassan II Casablanca
 

Plus de ENSET, Université Hassan II Casablanca (12)

Theses Soutenues sous Direction et Co-Direction du Pr YOUSSFI
Theses Soutenues sous Direction et Co-Direction du Pr YOUSSFITheses Soutenues sous Direction et Co-Direction du Pr YOUSSFI
Theses Soutenues sous Direction et Co-Direction du Pr YOUSSFI
 
Mise en oeuvre des Frameworks de Machines et Deep Learning pour les Applicati...
Mise en oeuvre des Frameworks de Machines et Deep Learning pour les Applicati...Mise en oeuvre des Frameworks de Machines et Deep Learning pour les Applicati...
Mise en oeuvre des Frameworks de Machines et Deep Learning pour les Applicati...
 
Support distributed computing and caching avec hazelcast
Support distributed computing and caching avec hazelcastSupport distributed computing and caching avec hazelcast
Support distributed computing and caching avec hazelcast
 
Mise en oeuvre des framework de machines et deep learning v1
Mise en oeuvre des framework de machines et deep learning v1 Mise en oeuvre des framework de machines et deep learning v1
Mise en oeuvre des framework de machines et deep learning v1
 
Conférence: Catalyseurs de l'Intelligence Artificielle et Écosystème des Fram...
Conférence: Catalyseurs de l'Intelligence Artificielle et Écosystème des Fram...Conférence: Catalyseurs de l'Intelligence Artificielle et Écosystème des Fram...
Conférence: Catalyseurs de l'Intelligence Artificielle et Écosystème des Fram...
 
Architecture jee principe de inversion de controle et injection des dependances
Architecture jee principe de inversion de controle et injection des dependancesArchitecture jee principe de inversion de controle et injection des dependances
Architecture jee principe de inversion de controle et injection des dependances
 
Support de cours angular
Support de cours angularSupport de cours angular
Support de cours angular
 
Support programmation orientée objet c# .net version f8
Support programmation orientée objet c#  .net version f8Support programmation orientée objet c#  .net version f8
Support programmation orientée objet c# .net version f8
 
Développement d'un site web jee de e commerce basé sur spring (m.youssfi)
Développement d'un site web jee de e commerce basé sur spring (m.youssfi)Développement d'un site web jee de e commerce basé sur spring (m.youssfi)
Développement d'un site web jee de e commerce basé sur spring (m.youssfi)
 
Maven et industrialisation du logiciel
Maven et industrialisation du logicielMaven et industrialisation du logiciel
Maven et industrialisation du logiciel
 
Systèmes multi agents concepts et mise en oeuvre avec le middleware jade
Systèmes multi agents concepts et mise en oeuvre avec le middleware jadeSystèmes multi agents concepts et mise en oeuvre avec le middleware jade
Systèmes multi agents concepts et mise en oeuvre avec le middleware jade
 
Support de Cours JSF2 Première partie Intégration avec Spring
Support de Cours JSF2 Première partie Intégration avec SpringSupport de Cours JSF2 Première partie Intégration avec Spring
Support de Cours JSF2 Première partie Intégration avec Spring
 

Cours design pattern m youssfi partie 2 observer

  • 1. DDeessiiggnn PPaatttteerrnnss PPaarrtt 22 Mohamed Youssfi Laboratoire Signaux Systèmes Distribués et Intelligence Artificielle (SSDIA) ENSET, Université Hassan II Casablanca, Maroc Email : med@youssfi.net Supports de cours : http://fr.slideshare.net/mohamedyoussfi9 Chaîne vidéo : http://youtube.com/mohamedYoussfi Recherche : http://www.researchgate.net/profile/Youssfi_Mohamed/publications med@youssfi.net
  • 2. Le ppaatttteerrnn OObbsseerrvveerr :: TTeenneezz vvooss oobbjjeettss aauu ccoouurraanntt
  • 3. DDeessiiggnn PPaatttteerrnnss dduu GGooFF ((GGaanngg ooff FFoouurr )) ((GGaammmmaa,, HHeellmm,, JJoohhnnssoonn,, VVlliissssiiddeess)
  • 4. PPaatttteerrnn OObbsseerrvvaatteeuurr CCCCaaaattttééééggggoooorrrriiiieeee : Comportement DDDDééééffffiiiinnnniiiittttiiiioooonnnn : ◦ LLee ppaatttteerrnn oobbsseerrvvaatteeuurr ddééffiinniitt uunnee rreellaattiioonn 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
  • 6. IImmpplléémmeennttaattiioonn Le diagramme UML du pattern Observateur définit deux interfaces et deux classes. ◦ L’interface Observateur sera implémenté par toutes classes qui souhaitent avoir le rôle d’observateur. ◦ C’est le cas de la classe ObservateurConcret qui implémente la méthode actualiser(Observable). Cette méthode sera appelée automatiquement lors d’un changement d’état de la classe observée. ◦ On trouve également une interface Observable qui devra être implémentée par les classes désireuses de posséder des observateurs. ◦ LLaa ccllaassssee OObbsseerrvvaabblleeCCoonnccrreett iimmpplléémmeennttee cceettttee iinntteerrffaaccee,, ccee qquuii lluuii permet de tenir informer ses observateurs. Celle-ci possède en attribut un état (ou plusieurs) et un tableau d’observateurs. L’état est un attribut dont les observateurs désirent suivre l’évolution de ses valeurs. Le tableau d’observateurs correspond à la liste des observateurs qui sont à l’écoute. ◦ En effet, il ne suffit pas à une classe d’implémenter l’interface Observateur pour être à l’écoute, il faut qu’elle s’abonne à un Observable via la méthode ajouterObservateur(Observateur).
  • 7. IImmpplléémmeennttaattiioonn La classe ObservableConcret dispose de quatre méthodes : ◦ ajouterObservateur(Observateur), ◦ supprimerObservateur(Observateur), ◦ notifierObservateurs() ◦ getEtat(). Les deux premières permettent, respectivement, d’ajouter des observateurs à l’écoute de la classe et d’en supprimer. EEnn eeffffeett,, llee ppaatttteerrnn OObbsseerrvvaatteeuurr ppeerrmmeett ddee lliieerr ddyynnaammiiqquueemmeenntt ((ffaaiirree uunnee 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. Celle-ci avertit tous les observateurs de cette mise à jour. La méthode getEtat() est un simple accesseur en lecture pour l’état. En effet, les observateurs récupèrent via la méthode actualiser(Observable) un pointeur vers l’objet observé. Puis, grâce à ce pointeur, et à la méthode getEtat() il est possible d’obtenir la valeur de l’état.
  • 8. IImmpplléémmeennttaattiioonn Il existe une variation possible lors de l’utilisation de ce pattern. ◦ TIRER : Dans la solution présentée, une référence vers l’objet observable est mis à disposition de chaque observateur. Ainsi les observateurs peuvent l’utiliser pour appeler la 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 l’information sur l’état. ◦ POUSSER :Mais il existe la solution inverse appelée « POUSSER ». DDaannss ccee ccaass,, oonn ppaassssee ddiirreecctteemmeenntt ll’’ééttaatt aaccttuueell ddee ll’’oobbsseerrvvaabbllee ddaannss llaa méthode actualiser(TypeEtat). Ainsi les observateurs disposent directement de l’état. Qu’elle est la meilleur solution entre les deux ? C’est la première parce qu’elle permet une fois de plus de lier faiblement l’observable à ses observateurs. En effet, si l’observateur dispose d’un pointeur vers l’objet observable et que la classe observable évolue en ajoutant un deuxième état. L’observateur souhaitant se tenir informé de ce deuxième état aura juste à appeler l’accesseur correspondant. Alors que si on « POUSSER » il faudrait changer la signature de la méthode ce qui peut s’avérer plus dommageable.
  • 10. CCaahhiieerr ddeess cchhaarrggeess Félicitation! Votre société a été retenue pour construire notre station météorologique de dernière génération consultable en ligne! La station sera basée sur notre objet DonneesMeteo (brevet en cours),qui enregistre les conditions météorologique à un moment donné (température, hygrométrie et pression atmosphérique). Nous aimerions que vous nous créiez une application qui fournira d’abord trois affichages: conditions actuelles, statistiques et prévisions simples, tous trois mis à jour en temps réel au fur et à mesure que l’objet DonneesMeteo acquiert les données les plus récentes. DDee pplluuss cceettttee ssttaattiioonn mmééttééoo ddooiitt êêttrree eexxtteennssiibbllee.. MMééttééooEExxpprreessss vveeuutt ccoommmmeerrcciiaalliisseerr une API pour que les autres développeurs puissent réaliser leurs propres affichages et les insérer directement. Nous souhaitons que vous nous fournissiez cette API ! MétéoExpress est convaincu d’avoir un excellent modèle métier: une fois les clients acrochés, nous prévoyons de les facturer pour chaque affichage qu’ils utilisent. Le meilleur est pour la fin : vous serez payé en stock options. Nous attendons avec impatience vos documents de conception et votre première version alpha Cordialement, Jean-Loup Ragan, PDG MétéoExpress P.S. Nous vous envoyons par chrono les fichiers source de DonnesMeteo
  • 11. Vue d’ensemble ddee ll’’aapppplliiccaattiioonn Les trois 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. CCaapptteeuurr Extrait d’humidité Capteur de température Capteur de pression Station météo Les données Objet DonneesMeteo Temp: 22° Hygro : 60 Pression : Dispositif a’affichage Affiche :DonneesMeteo Ce que MétéoExpress Fournit Ce que nous implémentons Si nous choisissons de l’accepter, notre tâche consiste à créer une application qui utilise l’objet DonneesMeteo qui actualise ces trois affichages: conditions actuelles, statistiques et prévisions
  • 12. A l’intérieur de la classe DDoonnnneeeessMMeetteeoo Le lendemain matin, les fichiers source de DonneesMeteo arrivent comme promis. Nous jetons un coup d’oeil au code qui semble relativement simple: DonneesMeteo Ces trois méthodes retournent les mesures les plus récentes : température, humidité, et pression atmosphérique. getTemperature() getHumidite() getPression() actualiserMesures() //Autres méthodes Nous n’avons pas besoin de savoir comment ces variables sont affectées; l’objet DonneesMeteo sait comment obtenir ces informations à jour. /* * Cette méthode est appelée chaque fois * que les mesures ont été mises à jour */ public void actualiserMesures(){ // Votre code ici }
  • 13. RRééccaappiittuulloonnss…….. 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. Nous ne savons pas comment cette méthode est appelée, et peu importe. Nous devrons implémenter trois affichages qui utilisent les données météorologiques: ◦ Un affichage des conditions actuelles ◦ Un affichage des statistiques ◦ UUnn aaffffiicchhaaggee ddeess pprréévviissiioonnss.. Ces trois affichages doivent être mis à jour, chaque fois que DonnesMeteo aquiert 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 ◦ Actuellement, nous ne connaissons que les trois types d’affichages initiaux Conditions actuelles Statistiques prévisions
  • 14. Premier essai ddee ssttaattiioonn mmééttééoo Voici une première possibilité d’implémentation: nous suivons l’indication des développeurs de MeteoExpress et nous ajoutons notre code à la méthode actualiderMesures(): public class DonneesMeteo{ //déclarations des variables d’instance public void actualiserMesures(){ 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 } AAAA vvvvoooossss ccccrrrraaaayyyyoooonnnnssss D’après notre première implémentation, quels énoncés suivants sont vrais? A. Nous codons des implémentations concrètes, non des interfaces B. Nous devons modifier le code pour chaque nouvel élément d’affichage C. Nous n’avons aucun moyen d’ajouter (ou de supprimer) des éléments d’affichage dynamiquement D. Les éléments d’affichage n’implémentent pas une interface commune E. Nous n’avons pas encapsulé les parties qui varient F. Nous violons l’encapsulation de la classe DonneesMeteo
  • 15. Qu’est ce qui cloche dans notre iimmpplléémmeennttaattiioonn Repenser à tous les concepts et les principes du chapitre précédent. public class DonneesMeteo{ //déclarations des variables d’instance public void actualiserMesures(){ float t=getTemperature(); float h=getHumidite(); float p getPression(); En codant des implémentation concrètes, nous n’avons aucun moyen d’ajouter ni de supprimer des affichageConditions.actualiser(t,h,p); affichageStats.actualiser(t,h,p); affichagePrevisions.actualiser(t,h,p); } // Autres méthodes } éléments sans modifier le programme Au moins, nous semblons utiliser une interface commune pour communiquer avec les affichages.. Ils ont tous une méthode actualier() qui lie les valeurs de temp, humidité et pression Points de variation : nous devons l’encapsuler
  • 16. Faites connaissance avec le ppaatttteerrnn OObbsseerrvvaatteeuurr Vous savez comment fonctionne un abonnement à un magazine: 1. Un éditeur se lance dans les affaires et commence à diffuser des magazines 2. vous souscrivez un abonnement 3. Chaque fois qu’il y’a une nouvelle édition, vous la recevez. Et tant que vous êtes abonné, vous recevez les nouvelles éditions. 4. Quand vous ne vouliez pas de ces magazines, 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. Si vous avez compris cet exemple, vous avez compris l’essentiel du patterns Observateur, sauf que nous appelons l’éditeur le SUJET et les abonnés les OBSERVATEURS
  • 17. Faites connaissance avec le ppaatttteerrnn OObbsseerrvvaatteeuurr Regardons de plus près Quand les données de l’objet sujet changent, les observateurs en sont informés. Donée=2 2 Objet Chien 2 Objet Sujet: Gère une donnée quelconque Objet Chat Objet Souris 2 Objet Canard Cet objet n’est pas un observateur : il n’est pas informés quand les données du sujet changent Les observateurs ont souscrit un abonnement ( se 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.
  • 18. Pattern Observateur :: ddééffiinniittiioonn Le pattern observateur définit une relation entre les objets de type un à pplluussiieeuurrss,, ddee ffaaççoonn qquuee,, lloorrssqquu’’uunn oobbjjeett change d’état, tous ce qui en dépendent en soient informés et soient mis à jour automatiquement
  • 19. Pattern Observateur : Diagramme ddee ccllaasssseess sujet Voici l’interface Sujet les objets utilise cette interface pour s’enregistrer comme observateur et pour résilier leur abonnement Tous les observateurs potentiels doivent implémenter l’interface Observateur. Cette interface n’a qu’une seule méthode actualiser() qui est appelée quand l’état du sujet change Chaque sujet peut avoir plusieurs observateurs observateurs Le sujet concret peut également avoir des méthodes pour accéder à son état (getEtat()) et le modifier (setEtat()) Un sujet concret implémente toujours l’interface Sujet. Outre les méthode d’ajout et de suppression d’observateurs, le sujet concret implémente la méthode notifierObservateurs() qui sert à mettre à jour tous les observateurs chaque fois que l’état change. Les observateurs concrets peuvent être n’importe quelle classe qui implémente l’interface Observateur. Chaque observateur s’enregistre au près du sujet réel pour recevoir les mises à jour; 1 *
  • 20. Le ppoouuvvooiirr dduu ffaaiibbllee ccoouuppllaaggee Lorsque deux 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 ni quoi que ce soit d’autre. ◦ Nous pouvons ajouter des observateurs à tout moment : CCoommmmee llee ssuujjeett ddééppeenndd uunniiqquueemmeenntt dd’’uunnee lliissttee dd’’oobbjjeettss qquuii iimmpplléémmeennttee ll’’iinntteerrffaaccee OObbsseerrvvaatteeuurr (observateurs:ArrayList), nous pouvons ajouter, supprimer, modifier des observateurs à volonté pendant l’exécution. Le sujet continue de fonctionner comme si rien n’était ◦ Nous n’avons jamais besoin de modifier le sujet pour ajouter de nouveaux types d’observateurs : Disons qu’une nouvelle classe concrète se présente et a besoin d’être un observateur, nous n’avons besoin d’ajouter quoi que ce soit au sujet pour gérer ce nouveau type. Il suffit qu’elle implémente l’interface Observateur, et de l’enregistrer entant que observateur. Le sujet continue de diffuser des notifications à tous les observateurs. ◦ 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
  • 21. Le ppoouuvvooiirr dduu ffaaiibbllee ccoouuppllaaggee Principe de conception: Efforcez-vous à coupler faiblement les objets qui interagissent 4er Principe de conception Les conceptions faiblement couplées nous 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.
  • 22. AA vvooss ccrraayyoonnss Avant de continuer, essayer d’esquisser les classes et les interfaces nécessaires pour implémenter la station météo, notamment la classe DonneesMeteo et lleess ccllaasssseess ddeess ddiifffféérreennttss aaffffiicchhaaggeess.. ◦ S’il vous faut un peu d’aide, lisez la page suivante : vos collègues sont déjà entrain de penser à la conception de la station météo.
  • 23. CCoonnvveerrssaattiioonn ddaannss uunn bbooxx Marie: Et bien, ça aide de savoir que nous utilisons le pattern Observateur. Anne: Oui… mais comment allons nous l’appliquer. Marie : regardons à nouveau la 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 Marie : ça a l’air claire quand on y pense : Notre classe DonneesMeteo est le « un », et le « plusieurs », ce sont les éléments qui affichent les différentes mesures; Anne : c’est vrai, la classe DonneesMeteo a avidement un état… la température, l’humidité, la pression atmosphérique, et bien sûr, ces données changent. Marie : Oui, et quand ces données changent, il faut notifier les éléments d’affichage pour qu’ils puissent mettre à jour l’affichage en utilisant les nouvelles mesures. Anne : super, maintenant je crois que je vois comment appliquer le pattern Observateur à notre problème. Marie : mais il y’a encore deux ou trois choses que je ne suis pas sûre d’avoir comprises. Anne : Pae exemple ? Marie : D’abord, comment faire pour que les éléments d’affichage puissent obtenir les mesures.
  • 24. CCoonnvveerrssaattiioonn ddaannss uunn bbooxx Anne: Eh bien, en regardant à nouveau le diagramme de classes du pattern Observateur, si nous faisons de l’objet DonneesMeteo le sujet et des éléments d’affichage les observateurs, alors les affichages vont s’enregistrer eux-mêmes auprès de l’objet DonneesMeteo pour obtenir les informations dont ils auront besoin, non ? Marie: Oui… et une fois que la station météo est au courant de l’existence d’un élément d’affichage, elle peut simplement appeler une méthode pour lui transmettre les mesures. Anne: Il faut se souvenir que chaque affichage peut être différent… et c’est là que je crois que qu’intervient une interface commune. Même si, chaque composant est d’un type différent, ils doivent implémenter tous une même interface pour que l’objet DonneesMeteo sache comment leur transmettre les mesures. Marie: je vois ce que tu veux dire. Chaque affichage aura par exemple une méthode actualier() que DonneesMeteo va appeler. Anne: Et actualiser() est définie dans une inteface commune que tous les éléments d’affichage implémenteront.
  • 25. Concevoir llaa ssttaattiioonn mmééttééoo Voici l’interface Sujet Tous nos composants implémentent l’interface Observateur. Ainsi le sujet dispose d’une interface à qui parler quand le moment est venu. Tous les affichages possèdent la méthode afficher(). Il implémentent donc cette interface observateurs sujet Ce composant affiche les mesures courantes obtenues de l’objet DonneesMeteo Cette classe Mémorise les mesures MIN, MOY et MAX et les affiche. Les développeurs peuvent développer leurs propres affichages Cette classe affiche une prévision en fonction de l’indicateur du baromètre DonneesMeteo implémente maintenant l’interface Sujet
  • 26. Implémenter llaa ssttaattiioonn mmeetteeoo Commençons par les interfaces 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(); }
  • 27. Implémenter l’interface sujet ddaannss DDoonnnneeeessMMeetteeoo 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); } }
  • 28. Implémenter l’interface sujet dans DDoonnnneeeessMMeetteeoo ((ssuuiittee)) public void notifierObservateurs() { for(int i=0;iobservateurs.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(); } }
  • 29. IImmpplléémmeenntteerr lleess aaffffiicchhaaggeess 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(); } }
  • 30. Mettre en route llaa ssttaattiioonn mmééttééoo TTeessttDDoonnnneeeessMMeetteeoo..jjaavvaa public class TestDonneesMeteo { public static void main(String[] args) { DonneesMeteo dm=new DonneesMeteo(); AffichageConditions ac=new AffichageConditions(dm); dm.setMesures(22,65,1020); dm:DonneesMeteo temp=22 hum=65 press=1020 Observateurs: ac:AffConditions temp=22 hum=65 dm.setMesures(25,75,1000); dm.setMesures(23,30,1800); } } 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é sujet: aa:AutreAffichage temp=22 press=1020 sujet:
  • 31. Utiliser le pattern OObbsseerrvvaatteeuurr ddee jjaavvaa Jusqu’ici, nous avons écrit notre propre code pour appliquer le pattern Observateur,mais java le prend en charge nativement dans plusieurs de ses API. Le cas le plus général est constitué d’une interface Observer et d’une classe Observable du package java.util. Elles sont très similaires à nos interfaces, mais elles apportent d’autres fonctionnalités « toutes prêtes ». Observable est une CLASSE, non une interface. Elle mémorise tous les observateurs et leurs envoie des notifications à votre place Cette interface devrait vous sembler familière. En effet, c’est la même que dans notre précédent diagramme de classes sauf que le nom de la méthode actualiser() est devenu update(). Voici notre Sujet que nous pouvons maintenant appeler l’Observable. Nous n’avons plus besoin d’implémenter les méthode enregistrer(), supprimer() et notifier(), car Nous avons omis l’interface Affichage, mais tous les affichages continuent à l’implémenter. Il y’aura quelques modification à apporter à la méthode update() nous avons hériter ce comportement de la classe Observable.
  • 32. Comment fonctionne le pattern OObbsseerrvvaatteeuurr eenn jjaavvaa Le pattern Observateur intégré à java fonctionne un peu différemment de l’implémentation que nous avons choisie pour notre première station météo. La différence la plus évidente réside dans le faite que DonneesMeteo (notre sujet) étend maintenant la classe Observable et nous héritons (entre autres) des méthodes addObserver(), deleteObserver() et notifierObservers(). Voici comment nous utilisons la version java de cet Observateur: ◦ Pour qu’un objet devient observateur… Comme d’habitude, implémenter l’interface Observer et appeler la méthode addObserver() de l’objet Observable. De même pour supprimer un observateur, il suffit d’appeler la méthode deleteObserver().
  • 33. Comment fonctionne le pattern OObbsseerrvvaatteeuurr eenn jjaavvaa ◦ Pour que l’observable envoie des notifications… Tout d’abord, il faut qu’il devienne Observable en étendant la super classe java.util.Observable. Puis l’on possède à deux étapes: Vous devez d’abord appeler la méthode setChanged(), pour signifier que l ’état de votre objet à changé Puis vous appelez l’une des deux méthodes notifyObservers(): public void notifyObservers() : méthode dans argument notifyObservers(Object arg) : méthode avec argument arg de type Object ◦ Pour qu’un observateur reçoive des notifications… Il implémente la méthode update comme auparavant, mais sa signature est diffère légèrement: Public void update(Observer o, Object arg ): Le premier paramètre représente le sujet qui envoyé la notification Le deuxième paramètre représente l’objet qui contient les données transmises à notifyObservers ou null si aucun objet n’a été spécifié. Si vous voulez pousser des données vers des observateurs, vous pouvez les transmettre sous forme d’objet donnée à la méthode notifyObservers(Object arg). Si non, l’observateur doit tirer les données de l’objet Observable qui lui a été transmis. ◦ Voyons comment faire tout cela dans notre station météo.
  • 34. MMéétthhooddee sseettCChhaannggeedd(()) ◦ Avant de commencer, on peut remarquer l’existence inhabituelle de la méthode setChanged() dans la classe Observable. ◦ A quoi sert donc cette méthode? ◦ RRééppoonnssee:: Cette méthode sert à signifier que l’état a changé et que notifyObservers(), quand elle est appelée, doit mettre à jour les observateurs. Si notifyObservers() est appelée sans qu’on ait d’abord appelé setChanged(), les observateurs ne seront pas notifiés. Jetons un coup d’oeil dans les coulisses de la classe Observable pour voir comment cala fonctionne.
  • 35. CCoouulliisssseess ddee OObbssaarrvvaallee protected void setChanged() { changed = true; } protected void clearChanged() { changed = false; } public void notifyObservers() { notifyObservers(null); } La méthode setChanged positionne un drapeau changed à true. La méthode clearChanged positionne le drapeau changed à false. public void notifyObservers(Object arg) { Object[] obsArr; if (!changed) return; obsArr = obs.toArray(); clearChanged(); for (int i = obsArr.length-1; i=0; i--){ Observer o=(Observer) obsArr[i]; o.update(this, arg); } } notifyObservers() ne notifie les observateurs que si la valeur du drapeau est true; Si le drapeau changed est true, elle le remet à false et puis notifie les observateurs
  • 36. Intérêt dduu ddrraappeeaauu cchhaannggeedd La méthode setChanged() est conçue pour vous autoriser plus de souplesse dans la façon dont vous mettez à jour les observateurs en vous permettant d’optimiser les notifications. Par exemple, ◦ Dans le cas de notre station météo, imaginez que les capteurs de mesures soient si sensibles que les températures affichées varient constamment de quelques dixième de degrés. ◦ LL’’oobbjjeett DDoonnnneeeessMMeetteeoo ppoouurrrraaiieenntt éémmeettttrree ddeess nnoottiiffiiccaattiioonn eenn ppeerrmmaanneennccee.. ◦ Mais si nous voulions émettre des notifications toutes moins fréquentes, nous n’appelons setChanged() que lorsque la température aura augmentée ou diminuée d’un demi degré. Vous n’utiliserez, peut-être pas très souvent cette fonctionnalité, mais sachez qu’elle existe en cas de besoin. Dans tous les cas, vous devez appeler la méthode setChanged() pour que les notifications soient effectuées. Comme vous pouvez également appeler clearChanged(), réinitialise le drapeau « changed » à false et la méthode hasChanged() qui retourne la valeur du drapeau.
  • 37. Retravailler la station météo avec llee ppaatttteerrnn OObbsseerrvveerr dduu ppaacckkaaggee jjaavvaa..uuttiill DDoonnnneeeessMMeetteeoo..jjaavvaa import java.util.Observable; public class DonneesMeteo extends Observable { private float temperature; private float humidite; private float pression; public DonneesMeteo(){} public float getHumidite() { return humidite; } public void actualiserMesures(){ setChanged(); notifyObservers(); }
  • 38. Retravailler la station météo avec llee ppaatttteerrnn OObbsseerrvveerr dduu ppaacckkaaggee jjaavvaa..uuttiill DDoonnnneeeessMMeetteeoo..jjaavvaa ((ssuuiittee)) public void setMesures(float t, float h, float p) { this.temperature=t; this.humidite=h; this.pression=p; actualiserMesures(); } public float getPression() { return pression; } public float getTemperature() { return temperature; } }
  • 39. AffichageConditions.jjaavvaa ((ssuuiittee)) import java.util.Observable; import java.util.Observer; public class AffichageConditions implements Observer,Affichage { Observable sujet; private float temperature; private float humidite; public AffichageConditions(Observable obs){ this.sujet=obs; sujet.addObserver(this); } public void update(Observable obs, Object arg) { if(obs instanceof DonneesMeteo){ DonneesMeteo dm=(DonneesMeteo)obs; this.temperature=dm.getTemperature(); this.humidite=dm.getHumidite(); afficher(); } } public void afficher() { System.out.println(Conditions actuelles:+ temperature+ degès et +humidite+ % d'hmidité); } }
  • 40. TTrraavvaaiill àà ffaaiirree Ecrire une implémentation de AffichagePrevisions de façon à afficher les messages suivants: ◦ « AAmméélliioorraattiioonn eenn ccoouurrss » ssii llaa ddiifffféérreennccee ddee pprreessssiioonn est positive ◦ « le temps se rafraîchit », si la différence de pression est négative. ◦ « Dépression bien installée », si la pression ne change pas.
  • 41. Autres endroits ou se trouve llee ppaatttteerrnn oobbsseerrvvaatteeuurr ddaannss llee JJDDKK.. Le composant Swing JButton est un sujet qui hérite de la classe AbstractButton. Si vous regarder la structure de cette classe vous regardez des méthodes comme add et remove qui permettent d’ajouter et de supprimer des observateurs qu’on appelle dans la terminologie de Swing des listenners (Auditeurs). Ces listeners sont à l’écoute des différents types d’événements qui peuvent se produire dans le composant JButton. Par exemple un ActionListener vous permet d’acouter tous les types d’actions qui peuvent être appliquées à un bouton, comme les clics. Si l’un des événements se produit sur le bouton, ce dernier notifie tous les observateurs qui sont de type ActionListener en faisant appel à la méthode actionPerformed() de chaque ActionListener.
  • 42. EExxeemmppllee ppoouurr llee ppllaaiissiirr AbstractButon JButton ActionListener actionPerformed() AuditeurAnge actionPerformed() AuditeurDemon actionPerformed() Console: Créer un JFrame Créer un JButton : Sujet Créer deux listeners ange et demon : Observateurs enregistrer les deux listeners chez le bouton en faisant appel à la méthode addActionListener() Si un utilisateur clique sur le bouton, son état change et tous les observateurs sont notifiés en exécutant leurs méthodes actionPerformed() Fais le tu as tout à gagner! Ne le fais pas, tu pourrais le regréter
  • 43. EExxeemmppllee ExObsSwing.java: import java.awt.*; import java.awt.event.*; import javax.swing.JButton; import javax.swing.JFrame; public class ExObsSwing{ private JFrame jf; private JButton bouton; // Créer un premier observateur qui implémente ActionListener class AutiteurAnge implements ActionListener{ public void actionPerformed(ActionEvent e) { System.out.println(Ne le fais pas, tu pourrais le regréter); } } // Créer un deuxième observateur qui implémente ActionListener class AutiteurDemon implements ActionListener{ public void actionPerformed(ActionEvent e) { System.out.println(Fais le tu as tout à gagner!); } }
  • 44. EExxeemmppllee public void go(){ jf=new JFrame(); // Créer le sujet bouton=new JButton(Dois-je le faire); // Créer deux observateurs ange et demon AuditeurAnge ange=new AuditeurAnge(); AuditeurDemon demon=new AuditeurDemon(); // Enregistrer les deux observateurs chez le bouton bouton.addActionListener(ange); bouton.addActionListener(demon); jf.getContentPane().setLayout(new FlowLayout()); jf.getContentPane().add(bouton); jf.setBounds(100,100,400,400); jf.show(); // Le bouton s’affiche dans la frame. // En cliquant sur celui-ci, tous les listeners enregistrés // chez le boutons sont notifiés et exécutent la méthode // actionPerformed(); équivalent à update() } public static void main(String[] args) { ExObsSwing ex=new ExObsSwing(); ex.go(); } }