Vous êtes sur la page 1sur 25

Patrons de comportement:

Observer/Observable
F. Mallet
miage.m1@gmail.com

http://deptinfo.unice.fr/~fmallet/

2011/2012 F. Mallet - Miage M1 6-1


Patrons de comportement: observer/observable

Motivation
Les besoins p
pour une bonne conception
p et
du bon code :
 Extensibilité
 Flexibilité
 Facilité à maintenir
 Réutilisabilité
 Les qualités internes
 Meilleure spécification, construction,
documentation

2010/2011 F. Mallet 2
Patrons de comportement: observer/observable

Historique
 MVC
 Gang of Four : Erich Gamma, Richard Helm,Ralph
Johnson, John Vlissides
 Définition de 23 patterns
 Design Patterns – Elements of Reusable Object-
Oriented Software,
Software Addison Wesley,
Wesley 1994
 Un Design Pattern nomme, abstrait et identifie les
aspects essentiels d’une
d une structuration récurrente
récurrente, ce
qui permet de créer une modélisation orientée objet
réutilisable

2010/2011 F. Mallet 3
Patrons de comportement: observer/observable

Classification
 Création
 Comment un objet peut être créé
 Indépendance entre la manière de créer et la manière
d utiliser
d’utiliser
 Structure
 Comment les objets peuvent être combinés
 Indépendance entre les objets et les connexions
 Comportement
 Comment les objets communiquent
 Encapsulation de processus (ex : observer/observable)

2010/2011 F. Mallet 4
Patrons de comportement: observer/observable

Ecouteur
Notifier
o e u un é
événement
é e e à qu
qui veut
eut

2010/2011 F. Mallet 5
Patrons de comportement: observer/observable

Compteur

Gestion de l’état Gestion de n


class Compteur { class CompteurModulo
private int etat = 0; extends Compteur {
private int modulo;
void incrementer(){
(){
this.etat += 1; void incrementer() {
} super.incrementer();
i t getEtat()
int tEt t() { if (getEtat()
( tEt t() == modulo){
d l ){
return this.etat; super.reset();
} }
void reset() { }
this.etat = 0; }
}
}
2010/2011 F. Mallet 6
Patrons de comportement: observer/observable

Compteur

Gestion de l’état Ecouteur


class Compteur {
private int etat = 0;
private CompteurListener ecouteur = null;
void incrementer(){
(){
this.etat += 1;
}
void
id reset()
t() {
if(ecouteur != null)
ecouteur.miseAZero(); interface CompteurListener {
this.etat = 0; void miseAZero();
} }
}
2010/2011 F. Mallet 7
Patrons de comportement: observer/observable

Compteur
class Compteur {
private
i t int
i t etat
t t = 0
0;
private CompteurListener ecouteur = null;
void incrementer(){
this.etat += 1;
}
void setListener(CompteurListener l){
ecouteur = l;
}
void reset() {
if(ecouteur != null)
ecouteur.misAZero();
();
this.etat = 0;
}
}
2010/2011 F. Mallet 8
Patrons de comportement: observer/observable

Horloge
class Horloge{
private CompteurModulo secondes,
secondes minutes;
Horloge(int sec, int min) {
this.secondes = new CompteurModulo(60, sec);
this min tes = new
this.minutes ne CompteurModulo(60,
Compte rMod lo(60 min)
min);

}
void
id incrementer()
i t () { // lles secondes
d
this.secondes.incrementer();
if(this.secondes.etat == 0)
incrementerMinutes();
}
void incrementerMinutes() {
this.minutes.incrementer();
}
}

2010/2011 F. Mallet 9
Patrons de comportement: observer/observable

miseAZero()
h incrementer()
h.incrementer()

incrementer()

Une horloge h: 12 min 59 secondes


h.incrementer();
h.secondes.incrementer();
h
h.secondes.ecouteur.miseAZero();
d t i AZ ()

2010/2011 F. Mallet 10
Patrons de comportement: observer/observable

Horloge
class Horloge {implements CompteurListener {
private CompteurModulo secondes,
secondes minutes;
Horloge(int sec, int min) {
this.secondes = new CompteurModulo(60, sec);
this min tes = new
this.minutes ne CompteurModulo(60,
Compte rMod lo(60 min)
min);
} this.secondes.setListener(this);
}
void
id incrementer()
i t () { // lles secondes
d
this.secondes.incrementer();
}
public void miseAZero() {
this.incrementerMinutes();
}
void incrementerMinutes() {
this.minutes.incrementer();
}
}
2010/2011 F. Mallet 11
Patrons de comportement: observer/observable

miseAZero()
h incrementer()
h.incrementer()

incrementer()

incrementer() 13

Une horloge h: 12 min 59 secondes


h.incrementer();
h.secondes.incrementer();
h.miseAZero();
h miseAZero();
h.secondes.ecouteur.miseAZero();
d t i AZ () h minutes incrementer();
h.minutes.incrementer();

2010/2011 F. Mallet 12
Patrons de comportement: observer/observable

Ecouteur et Décorateur
Un
U écou
écouteur
eu peu
peut e
en cac
cacher
e dd’autres
au es
class Ecouteurs implements CompteurListener {
ArrayList<CompteurListener> ecouteurs =
new ArrayList<CompteurListener>();
void add(CompteurListener e) {
ecouteurs.add(e);
t dd( )
}
public void miseAZero()
p () {
for(CompteurListener cl : ecouteurs)
cl.miseAZero();
}
}

2010/2011 F. Mallet 13
Patrons de comportement: observer/observable

Observer / Observable
Tout le monde p
peut être un Observer
(interface)
Observer
Observer "Arthur"
"Ludo"
S ’enregistre
Observable
Observable
1. Arthur
1 Arthur
1.
2 Martin
2. M ti
S ’enregistre

Observer
"Martin"
2011/2012 F. Mallet - Miage M1 14
Patrons de comportement: observer/observable
Observer / Observable
E
Exemple
l : un timer
ti
class Test {
Timer timer; toto est
écouteur
Test() { d timer
du ti
timer = new Timer();
Toto toto = new Toto();
timer.addObserver(toto);
}

static public void main(String[] args) {


Test t = new Test();
t.timer.run();
}
}
2011/2012 F. Mallet - Miage M1 15
Patrons de comportement: observer/observable
java.util.Observer
F estt un observateur
Foo b t
class Foo implements java.util.Observer {
public void update(Observable o, Object arg) {
System.out.println("Temps : "
+ ((Timer)o).getSeconds()
+ " secs");
}
}

Tous les observateurs doivent


posséder
d une méthode
h d update(…)
d ( )

2011/2012 F. Mallet - Miage M1 16


Patrons de comportement: observer/observable
java.util.Observable
E
Exemple
l
class Timer extends java.util.Observable
java util Observable {
private long zzz = 1000;
private long zero; Les observables doivent
spécialiser Observable
Timer(long zzz) {
this.zzz = zzz;
}

public void run () throws InterruptedException {


zero = System.currentTimeMillis();
while (true) {
setChanged();
tCh d()
notifyObservers(new Long(System.currentTimeMillis()
- zero));
TimeUnit.MILLISECONDS.sleep(zzz);
}
On notifie les observateurs
}
} … appel de update(…)

2011/2012 F. Mallet - Miage M1 17


Patrons de comportement: observer/observable

Créer ses propres classes d’écouteurs


d écouteurs
 Comment ça marche ?
 Créer ses propres classes d’écouteurs,
d’événements…
1. Ecrire l’interface que devront implémenter les
écouteurs (remplacer Observer/ActionListener)
2. Ecrire la classe qui correspond au nouveau type
d’événements (remplacer ActionEvent)
3 Ajouter des méthodes dans l’objet observable pour :
3.
• Pouvoir lui ajouter ou enlever des écouteurs
(addActionListener)),
• Prévenir les écouteurs en leur envoyant un objet
« événement » (notifyObservers)

2011/2012 F. Mallet - Miage M1 18


Patrons de comportement: observer/observable

Exemple avec un minuteur


 On va définir un minuteur envoie des événements de
type TimerEvent à ses écouteurs (de type
TimerListener) lorsqu’un certain temps s’est écoulé
 Ce minuteur est un Thread

2011/2012 F. Mallet - Miage M1 19


Patrons de comportement: observer/observable

L’interface
L interface TimerListener
package timer;
import java
java.util.*;
util *;

public interface TimerListener extends EventListener {


public void timerTriggered(TimerEvent e);
}

On peut choisir le
nom qqu’on veut ici !

2011/2012 F. Mallet - Miage M1 20


Patrons de comportement: observer/observable

La classe TimerEvent
package timer;
import java.util.EventObject ;

public
bli class
l Ti
TimerEvent
E t extends
t d E EventObject
tObj t {
public TimerEvent(Object source) {
super(source);
… // ici on peut stocker les
… // params supplémentaires éventuels
}
}
On peut ajouter d’autres paramètres,
mais le premier est obligatoire

2011/2012 F. Mallet - Miage M1 21


Patrons de comportement: observer/observable

La classe Timer
package timer;
import java.awt.event.*;
import java.util.*;

class Timer extends Thread {


public static final int DEFAULT_DELAY = 5000;
private int delayMs;
private ArrayList<TimerListener> timerListeners;

public
pub c Timer()
e () {
this(DEFAULT_DELAY);
}

public Timer(int delayMs) {


this.delayMs = delayMs;
}

2011/2012 F. Mallet - Miage M1 22
Patrons de comportement: observer/observable

La classe Timer (suite)


public synchronized void removeTimerListener(TimerListener l) {
if (ti
(timerListeners
Li t ! null)
!= ll) {
timerListeners.remove(l);
}
}

public synchronized void addTimerListener(TimerListener l) {


if (
(timerListeners == null)
)
timerListeners = new ArrayList<TimerListener>();
timerListeners.add(l);
}

2011/2012 F. Mallet - Miage M1 23


Patrons de comportement: observer/observable

La classe Timer (suite)


protected void fireTimerTriggered(TimerEvent e) {
if (timerListeners == null) return;
for(TimerListener tl : timerListeners)
tl timerTriggered(e);
tl.timerTriggered(e);
}

Notification des écouteurs


public void run () {
while (!canceled)
try
y {
TimeUnit.MILLISECONDS.sleep(delayMs);
fireTimerTriggered(new TimerEvent(this));
} catch
t h (E
(Exception
ti e)
) { }
}
}

2011/2012 F. Mallet - Miage M1 24


Patrons de comportement: observer/observable

Exemple d’écouteur
d écouteur
import timer.*;
timer. ; Classe interne anonyme
y
public class TestTimer { dans cet exemple…
Timer timer1 = new Timer(1000);
public TestTimer() {
timer1.addTimerListener(new TimerListener() {
public void timerTriggered(TimerEvent e) {
System.out.println("Une sec s’est écoulée…");
}
});
timer1.start();
}
}

2011/2012 F. Mallet - Miage M1 25

Vous aimerez peut-être aussi