Sie sind auf Seite 1von 59

NFP121

1
NFP121, Cnam/Paris
Cours 4
Patrons Observateur/MVC
programmation vnementielle
Notes de cours
jean-michel Douin, douin au cnam point fr
version : 14 Octobre 2010
NFP121
2
Sommaire
Patron Observateur
Programmation vnementielle
Patron MVC Modle Vue Contrleur
Patron Publish-Subscribe en annexe
NFP121
3
Principale bibliographie utilise
[Grand00]
Patterns in Java le volume 1
http://www.mindspring.com/~mgrand/
[head First]
Head first : http://www.oreilly.com/catalog/hfdesignpat/#top
[DP05]
Lextension Design Pattern de BlueJ : http://hamilton.bell.ac.uk/designpatterns/
[divers]
Certains diagrammes UML : http://www.dofactory.com/Patterns/PatternProxy.aspx
informations gnrales http://www.edlin.org/cs/patterns.html
NFP121
4
Patrons/Patterns pour le logiciel
Origine C. Alexander un architecte
Abstraction dans la conception du logiciel
[GoF95] la bande des 4 : Gamma, Helm, Johnson et Vlissides
23 patrons/patterns
Architectures logicielles
NFP121
5
Introduction : rappel
Classification habituelle
Crateurs
Abstract Factory, Builder, Factory Method Prototype Singleton
Structurels
Adapter Bridge Composite Decorator Facade Flyweight Proxy
Comportementaux
Chain of Responsability. Command Interpreter Iterator
Mediator Memento Observer State
Strategy Template Method Visitor
NFP121
6
Les patrons dj vus
Adapter
Adapte linterface dune classe conforme aux souhaits du client
Proxy
Fournit un mandataire au client afin de contrler/vrifier ses accs
NFP121
7
Patron Observ/observateur 1)
Notification dun changement dtat
dune instance aux observateurs inscrits
Un Observ
Nimporte quelle instance qui est modifie
i.e. un changement dtat comme la modification dune donne dinstance
usage dun mutateur, par exemple
Des Observateurs, ils seront notifis
A la modification de lobserv,
Synchrone, ( et sur la mme machine virtuelle)
NFP121
8
Patron Observ/observateur 2)
Plusieurs Observs / un observateur
Un Observateur peut observer plusieurs instances
Plusieurs Observs / plusieurs observateurs
Ajout et retrait dynamiques dobservateurs
NFP121
9
UML & le patron Observateur, loriginal
http://www.codeproject.com/gen/design/applyingpatterns/observer.gif
NFP121
10
Observateur en Java
Lors dun changement dtat notification aux observateurs inscrits
public interface Observer{
public void update(Observable o);
}
public interface Observable{
public void addObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObservers();
public int getState();
public void setState(int state);
}
NFP121
11
ConcreteObservable
public class ConcreteObservable implements Observable{
private Collection<Observer> observers = new
private int state = 0;
public void addObserver(Observer observer){
observers.add(observer);
}
public void removeObserver(Observer observer){
observers.remove(observer);
}
public void notifyObservers(){
for(Observer obs : observers)
obs.update();
}}
public void setState(int state){
this.state = state;
notifyObservers();
}}
public int getState(){return this.state;}
NFP121
12
Observer : mise en oeuvre
Observable o = new ConcreteObservable();
Observer obs1= new ConcreteObserver();
o.addObserver(obs1);
o.setState(3); // obs1 est rveill, notifi
Observer obs2= new ConcreteObserver();
o.addObserver(obs2);
o.setState(33); // obs1 et obs2sont rveills, notifis
NFP121
13
Dmonstration / discussion
Variante syntaxique
Observ est une classe abstraite
Observateur est une interface
Une liste est un Observ concret
Un Observateur de Liste implmente linterface Observateur
NFP121
14
Notification amlioration
Lobservable pourrait tre encapsul :
public interface Observer{
public void update(Source src);
}
Class Source
Observable obs;
Object Paramtre
}
ou nous pourrions ajouter des paramtres
public interface Observer{
public void update(Observable o, Object erg);
}
public interface Observer{
public void update(Observable o);
}
NFP121
15
Observer : Encapsulation, EventObject
A chaque notification un event object est transmis
public interface Observer{
public void update(java.util.EventObject evt);
}
package java.util;
public class public class public class public class EventObject EventObject EventObject EventObject extends extends extends extends Object Object Object Object implements implements implements implements Serializable Serializable Serializable Serializable{ {{ {
public public public public EventObject EventObject EventObject EventObject( (( (Object Object Object Object source){ } source){ } source){ } source){ }
public public public public Object Object Object Object getSource getSource getSource getSource(){ } (){ } (){ } (){ }
public public public public String String String String toString toString toString toString(){ } (){ } (){ } (){ }
} }} }
NFP121
16
Observ/Observateurs
Prdfinies paquetage java.util
NFP121
17
java.util, java.awt.event et plus
java.util.Observer & java.util.Observable
update addObserver
NFP121
18
java.util.Observer
public interface Observer{
void update(Observable o, Object arg);
}
LObserv est transmis en paramtre Observable o
accompagn ventuellement de paramtres Object arg
update est appele chaque notification
NFP121
19
java.util.Observable
public class Observable{
public void addObserver(Observer o) ;
public void deleteObserver(Observer o) ;
public void deleteObservers() ;
public int countObservers() ;
public void notifyObservers() ;
public void notifyObservers(Object arg) ;
public boolean hasChanged() ;
protected void setChanged() ;
protected void clearChanged() ;
}
NFP121
20
Un Exemple : une liste et ses observateurs
Une liste est observe, chaque modification de celle-ci,
ajout, retrait, les observateurs inscrits sont notifis
public class Liste<E> extends java.util.Observable{

public void ajouter(E e){


// modification effective de la liste
setChanged(); // ltat de cette liste a chang
notifyObservers(e); // les observateurs sont prvenus
}
Une liste ou nimporte quelle instance
NFP121
21
Un Exemple : un observateur de la liste
Liste<Integer> l = new Liste<Integer>();
l.addObserver( new Observer(){
public void update(Observable o,Object arg){
System.out.print( o + " a chang, " );
System.out.println( arg + " vient d'tre ajout !");
}
});
Cest tout ! dmonstration Cest tout ! dmonstration Cest tout ! dmonstration Cest tout ! dmonstration
NFP121
22
Observateur comme Listener
java.awt.event.EventListener
Les couteurs/observateurs sont tous des EventListener
Convention syntaxique de Sun pour ses API
XXXXXListener extends EventListener
update
addXXXXXListener
addObserver
exemple linterface ActionListener / addActionListener
EventObject Source de la notification,
XXXXXEvent extends EventObject
exemple ActionEvent
NFP121
23
Observateur comme XXXXListener
Une grande famille !
NFP121
24
Une IHM et ses couteurs
Chaque item est un sujet observable avec ses couteurs
Pour un Bouton , chaque clic les couteurs/observateurs sont prvenus
public class Button extends Component{

public void addActionListener(ActionListener al){


}
NFP121
25
Un bouton prvient ses couteurs
Button b = new Button("empiler");
b.addActionListener(unEcouteur); // 1
b.addActionListener(unAutreEcouteur); // 2
b.addActionListener(
new ActionListener(){ // 3 couteurs
public void actionPerformed(ActionEvent ae){
System.out.println("clic !!! ");
}
});
Une instance de la classe java.awt.Button
prvient
ses instances inscrites java.awt.event.ActionListener
NFP121
26
Un couteur comme Action Listener
import java.util.event.ActionListener;
import java.util.event.ActionEvent;
public class EcouteurDeBouton
implements ActionListener{
public void actionPerformed(ActionEvent e){
// traitement chaque action sur le bouton
}
}
//c.f. page prcdente
ActionListener unEcouteur = new EcouteurDeBouton();
b.addActionListener(unEcouteur); // 1
NFP121
27
Dmonstration / Discussion
NFP121
28
API Java, patron Observateur, un rsum
Ajout/retrait dynamiques des observateurs ou couteurs
Lobservable se contente de notifier
Notification synchrone tous les observateurs inscrits
API prdfinies java.util.Observer et java.util.Observable
Listener comme Observateur
La grande famille des EventListener / EventObject
NFP121
29
patrons Observer / MVC
Modle Vue Contrleur
agit, modifie le Modle
Observs
/ Observateurs
NFP121
30
MVC : Observer est inclus
Observable
Modle
Observer
Vue
(update)
(getState)
(setState)
Contrleur
NFP121
31
MVC : exemple de capteurs
Une architecture simple et souple
Capteurs
Contrleur
Liste des mesures
Modle
Histogramme
Vue
(1)
(2)
(3)
NFP121
32
MVC Avantages
Souple ?
Capteurs
Contrleur
Liste des mesures
Modle
(1)
Capteurs
Contrleur
Capteurs
Contrleur
Capteurs
Contrleur
Capteurs
Contrleur
Capteurs
Contrleur
(1)
Histogramme
Vue
(3)
Histogramme
Vue
Histogramme
Vue
Histogramme
Vue
Histogramme
Vue
graphique
Vue
(2)
(2)
(3)
NFP121
33
Un cycle MVC
Utilisateur
Contrleur Vue
Modle
1
2
inscription
3
4
NFP121
34
Un cycle MVC, le bouton empiler
Utilisateur
Contrleur Vue
Modle
Clic !
empiler
inscription
notification
4
NFP121
35
Dmonstration / MVC en pratique
Un Modle
Plusieurs Contrleurs
Plusieurs Vues
NFP121
36
Dmonstration : le Modle i.e. un Entier
import java.util.Observable;
public class Modle extends Observable{
private int entier;
public int getEntier(){
return entier;
}
public String toString(){
return "entier : " + entier;
}
public void setEntier(int entier){
this.entier = entier;
setChanged();
notifyObservers(entier);
}
}
Vue
Modle
update
notifyObservers
NFP121
37
Dmonstration : une Vue
public interface Vue{
public void afficher();
}
import java.util.Observable;
import java.util.Observer;
public class Vue1 implements Vue, Observer{
private Modle modle;
public Vue1( Modle modle){ // inscription auprs du modle
this.modle = modle;
modle.addObserver(this);
}
public void afficher(){
System.out.println(" Vue1 : le modle a chang : " + modle.toString());
}
public void update(Observable o, Object arg){ // notification
if(o==modle) afficher();
}
}
Vue
Modle
toString
afficher
update
NFP121
38
Dmonstration : un contrleur
public class Contrleur1{
private Modle modle;
public Contrleur1(Modle modle){
this.modle = modle;
}
public void incrmenter(){
modle.setEntier(modle.getEntier() +1);
}
}
Contrleur
Modle
setEntier
incrmenter
NFP121
39
Un modle, une vue, un contrleur
// Un Modle
Modle modle = new Modle();
// Ce modle possde une vue
Vue vue = new Vue1(modle);
// un Contrleur ( dclenche certaines mthodes du modle)
Contrleur1 contrleur = new Contrleur1(modle);
contrleur.incrmenter();
contrleur.incrmenter();
}
NFP121
40
Un modle, deux vues, deux contrleurs
// Un Modle
Modle modle = new Modle();
// deux vues
Vue vueA = new Vue1(modle);
Vue vueB = new Vue1(modle);
// 2 Contrleurs
Contrleur1 contrleurA = new Contrleur1(modle);
Contrleur1 contrleurB = new Contrleur1(modle);
contrleurA.incrmenter();
contrleurB.incrmenter();
NFP121
41
Discussion
Modle
(1)
Capteurs
Contrleur
ContrleurA
(1)
(3)
Histogramme
Vue
VueA
(2)
(2)
(3)
NFP121
42
AWT / Button, discussion
Un Button (le contrleur) contient un MVC
part entire
Text, TextField, Label, sont des Vues
Button, Liste, sont des contrleurs
Une IHM (JApplet,) contient la Vue et le Contrle
Alors le compromis architecture/lisibilit est rechercher
NFP121
43
Un JButton comme MVC
Au niveau applicatif appel de tous les observateurs inscrits
actionPerformed(ActionEvent ae ), interface ActionListener
Utilisateur
IHM JButton Vue du JButton
JButton
Clic !
change
Modifier laspect du
JButton
4
NFP121
44
Proposition c.f. le TP
MVC propos :
Le Contrleur est un JPanel,
Transforme les actions sur les boutons ou lentre dune oprande en oprations sur le Modle
Le Modle est une Pile
Est un Observable
La Vue est un JPanel,
Observateur du Modle, la vue affiche ltat du Modle chaque notification
contrleur
Vue
ou bien Le Modle est une calculette qui utilise une pile
Est un Observable
NFP121
45
C
modle
pile
V
Proposition : MVC Imbriqus
Architecture possible
Le contrleur inclut la gestion des actions de lutilisateur
Niveau 1 : Gestion des Listeners
Niveau 2 : Observable et Observer
NFP121
46
MVC doc de Sun
http://java.sun.com/blueprints/patterns/MVC-detailed.html
NFP121
47
Nouvelle Proposition
MVC propos :
Le Contrleur implmente tous les listeners
Transforme les actions sur les boutons ou lentre dune oprande en oprations sur le Modle
Le Modle est une Pile
Est un Observable
La Vue est un JPanel,
Observateur du Modle, la vue affiche ltat du Modle chaque notification
contrleur
Vue
Le Modle est une calculette qui utilise une pile
Est un Observable
NFP121
48
IHM et MVC assez rpandu
Discussion
Evolution, maintenance, la recherche du couplage faible
Exemple
peut-on changer dIHM ?, peut-elle tre supprime ?
peut-on placer le modle sur une autre machine ?
NFP121
49
Conclusion
MVC
Trs utilis
Couplage faible obtenu
Intgration claire du patron Observateur
Modle Vue Contrleur (MVC) est une mthode de conception pour le dveloppement
d'applications logicielles qui spare le modle de donnes, l'interface utilisateur et la logique
de contrle. Cette mthode a t mise au point en 1979 par Trygve Reenskaug, qui travaillait
alors sur Smalltalk dans les laboratoires de recherche Xerox PARC
[1]
.
Extrait de http://fr.wikipedia.org/wiki/MVC
NFP121
50
Observer distribu ? Un petit pas franchir
Synchrones/asynchrones ?
Technologies java comme rmi, JMS (Java Messaging Service), JINI
Voir le Patron publish-subscribe
Observable
1) notifyObservers
Observer A
Observer B
Observer C
2) update
3) update
4) update
NFP121
51
Annexe : web MVC, JSP model
Web MVC rechercher sur le web voir aussi Multi-model MVC
NFP121
52
Publish-subscribe
Patron Observateur/Observ
Les observateurs sont rveills chaque notification
Filtrage des sources dvnements ?
Patron Publish/Subscribe
Observateurs inscrits auprs dun mdiateur pour un thme
Les Observs notifient au mdiateur sur ce thme
NFP121
53
Publish/subscribe
Extrait de http://www2.lifl.fr/icar/Chapters/Intro/intro.html
NFP121
54
Un exemple, le diagramme de squences
Une notification dvnements mto et de valeurs dun sensor (p1,p2 : Publisher),
Un mdiateur de gestion des abonnements et de notifications (mediator),
Deux souscripteurs aux thmes mto et sensor (s1, s2 : Subscriber).
mediator : Mediator
p1 : Publisher
s1 : Subscriber
s2 : Subscriber
p2 : Publisher
addSubscriber (s1, meteo )
publish (p1, meteo ,"sun ")
update (p1, meteo ,"sun ")
addSubscriber (s2, sensor )
publish (p2, sensor ,"25")
update (p1, meteo ,"rain ")
publish (p1, meteo ,"rain ")
publish (p1, meteo ,"sun ")
update (p1, meteo ,"sun ")
publish (p2, sensor ,"27")
update (p2, sensor ,"27")
addSubscriber (s2, meteo )
publish (p1, meteo ,"sun ")
update (p1, meteo ,"sun ")
update (p1, meteo ,"sun ")
NFP121
55
Diagramme de classes UML/BlueJ
NFP121
56
MediatorI
public interface MediatorI{
/** Ajout d'un souscripteur pour ce thme de publication.
* Une seule occurrence dun souscripteur par thme.
* @param subscriber le souscripteur.
* @param topic le thme de publication.
*/
public void addSubscriber(SubscriberI subscriber, Topic topic);
/** Publication sur ce thme.
* Appel de la mthode update de chaque souscripteur
* @param source l'metteur de la publication.
* @param topic le thme de publication.
* @param arg les arguments lis au thme.
*/
public void publish(Object source, Topic topic, Object arg);
}
NFP121
57
SubscriberI, PublisherI
public interface SubscriberI{
/** Notification sur ce thme.
* @param source l'metteur.
* @param topic le thme de publication.
* @param arg les arguments lis au thme.
*/
public void update(Object source, Topic topic, Object arg);
}
public interface PublisherI{
/** Notification sur ce thme.
* @param mediator le mediator concern.
* @param topic le thme de publication.
* @param arg les arguments lis au thme.
*/
public void publish(MediatorI mediator, Topic topic, Object arg);
}
NFP121
58
Topic, les thmes possibles
public class Topic implements Serializable{
public final static Topic ALL = new Topic(){
public String toString(){
return "TOPIC_ALL";
}
};
// mthodes toString, equals et hashCode redfinies
//
}
les classes Meteo et Sensor, hritent de Topic.
Si un souscripteur souhaite tre notifi quelque soit le thme,
il choisira le thme la constante Topic.ALL.
NFP121
59
Main, associ au diagramme de squences
public static void main(String[] args) throws Exception{
Topic meteo = new Meteo();
MediatorI mediator = new Mediator();
SubscriberI s1 = new Subcriber("s1");
PublisherI p1 = new Publisher("p1");
mediator.addSubscriber(s1, meteo);
mediator.publish(p1,meteo,"sun");
mediator.publish(p1,meteo,"rain");
Topic sensor = new Sensor();
PublisherI p2 = new Publisher("p2");
SubscriberI s2 = new Subcriber("s2");
mediator.addSubscriber(s2, sensor);
mediator.publish(p1,meteo,"sun");
mediator.addSubscriber(s2, meteo);
mediator.publish(p2,sensor,"27");
mediator.publish(p1,meteo,"sun");
}