Upload
ancel-peres
View
113
Download
1
Embed Size (px)
Citation preview
Cours JAVA / Y.Laborde
1Java : Modèle / Vues / Contrôleurs
LES CONCEPTS du paradigme MVC : Introduction L’implémentation MVC dans Java
le package java.util la classe java.util.Observable l’interface java.util.Observer
La méthode notifyObservers(Object arg) nécessité de l’argument non nul une classe de messages : WhatChanged
La technique du modèle interfacé en strates dérivations successives du modèle (strates) interfaçage par strates du modèle
(diapo 5)
(5)
(6)
(7)
(8)
(9)
(xx)
(xx)
Cours JAVA / Y.Laborde
2Java : MVC / Introduction
Le paradigme MVC (Modèle / Vues / Contrôleurs) est conçu pour les applications possédant une forte interactivité avec l’utilisateur. De fait, il est parfaitement adapté aux applicatifs dotées d’une IHM.
C’est une technique de programmation basée sur le développement modulaire.
En effet, toute application interactive peut a priori être découpée en 3 parties :- le modèle (éventuellement architecturé en modèle principal et modèles secondaires)
- les vues- les contrôleursQuel est le rôle du modèle ?
Son rôle est de conserver l’état des données spécifiques à l’applicatif et de réaliser les traitements algorithmiques afférents.Exemple de la calculatrice :C’est tout ce qui réalise les opérations mathématiques, les conversions, la mise en mémoire de valeurs, la vérification du parenthésage, …
Quel sont les rôles des vues ?
Leur rôle est de maintenir à jour, en totalité ou en partie, une représentation (graphique) de l’état courant du modèle et de fournir l’interactivité nécessaire.Exemple de la calculatrice :Ce sont tous les composants graphiques comme l’afficheur du résultat, l’afficheur de présence d’une valeur mémorisée, l’activation ou non d’une commande, … ainsi que la Frame, les boutons, …
Quel sont les rôles des contrôleurs ?
Leur rôle est de définir le comportement des vues vis-à-vis des interactions (clavier, souris, …) et de les acheminer sous forme d’événements aux vues.Exemple de la calculatrice :Ce sont tous les Listener mis en place : ActionListener, TextListener, WindowListener, …
Cours JAVA / Y.Laborde
3Java : MVC / Introduction
Le concept de modularité sous-jacent à la technique MVC oblige à ce que les modules communiquent entre eux.
Mise à part l’initialisation des liens à l’instanciation des modules, les communications entre modules peuvent être de plusieurs types :
modèle vers vues vues vers modèle contrôleur vers vues
ModèleDeCalculatrice
Modèle
AfficheurRésultatContrôleur
Contrôleurs
BoutonsOpérationsBinairesCont
rôleur
…
AfficheurRésultat
Vues
Bouton « + »
Bouton « = »
…
AfficheurRésultatAdapteur
BoutonsOpérationsBinairesAdap
teur
…
Composants Ecouteurs
=
+
click
JVM (WM)(1)
(1) JVM (WM) : la JVM prévient le contrôleur Java en encapsulant un événement approprié
1C => 1V
(2)
(2) 1C => 1V : le contrôleur Java achemine le message vers l’adaptateur de vue intéressée
1V => M
(3)
(3) 1V => M : l’adaptateur de la vue prévient le modèle de l’interaction utilisateur
M => *V
(4)
(4) M => *V : le modèle CHANGE SON ETAT INTERNE puis fait la demande à CHAQUE VUE (inscrite) de se mettre à jour pour refléter ce nouvel état.Ici, c’est principalement AfficheurRésultat qui devra modifier la valeur affichée.
Cours JAVA / Y.Laborde
4Java : MVC / Introduction
Ainsi avec le paradigme MVC :
- chaque contrôleur communique avec une vue - chaque vue communique avec un modèle (et éventuellement avec des sous-
modèles)
mais
- le modèle communique toujours avec de nombreuses vues sans véritablement les distinguer les unes des autres. Il ne fait que les informer que son état a changé. Aux vues de se mettre à jour pour représenter correctement le nouvel état du modèle.
Cela est dû à la fonction même du modèle :
* protéger les données propres à l’applicatif en les encapsulant, * faire évoluer les données (sans risquer leur incohérence) à l’aide
d’algo-rithmes internes « parfaitement sûrs », * informer les vues de tout changement d’état, * fournir des méthodes « sûres » permettant aux vues de connaître
l’état du modèle.
Il en découle tous les avantages de la modularité (réutilisabilité, maintenance aisée, développement en équipe, application à de grands projets, …).
Cours JAVA / Y.Laborde
5Java : MVC / le package java.util
L’implémentation MVC de Java consiste à fournir DEUX entitéstoutes les deux implémentées dans le package « java.util ».
Observable
Observer
Les entités MVC de Java
public classe
Object
public interface
Le MODELE doit dériver cette classe pour devenir OBSERVABLE
par des VUES
Les VUES doivent implémenter cette interface pour devenir OBSERVATRICES
de MODELES
public ModèleDeCalculatrice extends java.util.Observable
public BoutonsOpérationsBinairesPanel extends java.awt.Panel implements java.util.Observer , java.awt.event.ActionListenerpublic AfficheurRésultat extends java.awt.TextField implements java.util.Observer , java.awt.event.TextListener
Les CONTRÔLEURS sont « transparents » en Java.
Ils sont en grande partie implémentés par la JVM.
Cours JAVA / Y.Laborde
6Java : MVC / la classe java.util.Observable
public class java.util.Observable extends Object
Cette classe représente un modèle Observable. Elle doit être dérivée pour obtenir un modèle applicatif.
Un modèle peut avoir un ou plusieurs « observateurs ». Ceux-ci devront s’inscrire auprès du modèle observable pour que celui-ci puisse leur envoyer les messages de mise à jour à chaque changement de son état.
Pour cela, après qu’un Observable change d’état, il doit invoquer SetChanged() puis notifyObservers(…) pour que tous ses Observer soit notifiés du changement par l’appel de leur méthode update(…).
L’ordre dans lequel les Observer sont notifiés ne fait l’objet d’aucune spécification.
Object Observable
CONSTRUCTEURS :public Observable ()
METHODES :public void addObserver (Observer o) => pour inscrire un Observer (une vue)
protected void setChanged ( ) => sans appel de cette méthode, les 2 suivantes ne font rien !
public void notifyObservers ( ) => si le flag de changement est positionné, notifie TOUS les
public void notifyObservers (Object arg) Observer inscrits (avec l’argument vide ou non)
public boolean hasChanged ( ) => indique l’état du flag de changement du modèle
Cours JAVA / Y.Laborde
7Java : MVC / l’interface java.util.Observer
public interface java.util.Observer
Une classe peut implémenter cette interface lorsqu’elle veut être informée des changements d’un objet Observable (i.e. un modèle). Ce dernier invoquera la méthode update(…) de l’Observer à chaque fois que son état interne aura changé.
Observer
METHODES :public void update (Observable o, Object arg) Observable o, le modèle qui a envoyé ce message. Cela permet de retrouver le modèle dont l’état a changé
de sorte à le questionner pour connaître son état. Ce paramètre peut faire l’objet d’un cast en cas de certitude sur la classe du modèle.
Object arg, un paramètre objet fournit par le modèle ( méthode notifyObservers(Object arg) ) pour renseigner sur la nature du changement. Lorsque la notification par le modèle est effectuée par appel de la méthode notifyObservers() sans paramètre, cela invoque notifyObservers(null). La méthode update(Object arg) reçoit alors une référence nulle dans arg.
Cours JAVA / Y.Laborde
8Java : MVC / la méthode notifyObservers(Object arg)
Nécessité de l’argument non nul
Cette méthode peut être utilisée lorsque l’on désire fournir des renseignements aux vues sur la nature du changement produit dans le modèle.
En effet, dans le cas d’un applicatif possédant un état tel que des changements peuvent intervenir dans certaines parties et pas dans d’autres.exemple:la calculatrice montre à la fois le résultat du calcul et l’indicateur de présence d’une valeur en mémoire ; or parfois le modèle changera à cause d’un nouveau résultat à afficher et parfois à cause d’une modification de l’indicateur de mémoire.
Si le modèle envoie un message notifyObservers() sans argument, chaque vue recevant ce message est invitée à rafraîchir sa représentation sans savoir si la partie de modèle qu’elle représente a véritablement changée ou non. Or, en général, le modèle n’est pas en mesure, après coup, d’informer les vues sur l’aspect qui vient de changer.Ainsi, certaines vues vont devoir se rafraîchir alors qu’elles n’en auraient pas besoin !
Cours JAVA / Y.Laborde
9Java : MVC / une classe de messages : WhatChanged
Une méthode correcte consiste àconstruire une classe
WhatChanged :
- contenant des messages prédéfinis
- et capable d’accepter tous typesd’objets permettant de préciserles changements intervenusdans le modèle.
class WhatChanged {
// messages indiquant la nature du changement
static public String WC_RESULTAT = “WC_RESULTAT”;
static public String WC_IND_MEM = “WC_IND_MEM”;
...
// Variables d’instance
public String mess;
public Object 01,02; // 03,04,… si nécessaire !
// Constructeurs utiles
public WhatChanged(String _mess) {
this.mess = _mess; } // O1 et 02 sont nuls
public WhatChanged(String _mess, Object _01) {
this.mess = _mess;
this.O1 = _O1; } // 02 est nul
public WhatChanged(String _mess
, Object _01 ,Object _02) {
this.mess = _mess;
this.O1 = _O1;
this.O2 = _O2; }
}
Ici, les deux messages définis correspondent à un changement du résultat
(WC_RESULTAT) et à un changement de l’indicateur de valeur en mémoire
(WC_IND_MEM).D’autres messages peuvent être ajoutés.
Ici, deux objets O1 et O2 permettent au modèle de transmettre des informations
complexes aux vues.Mais ces dernières doivent connaître le type
d’objets effectivement transmis pour pouvoir effectuer un cast et retrouver leur contenu.
Cours JAVA / Y.Laborde
10Java : MVC / exemple d’utilisation de WhatChanged
class ModèleDeCalculatrice extends
java.util.Observable {
// Variables d’instance du modèle
protected double result, oldResult;
protected char oldOperator;
protected double memoryValue;
protected boolean oldResultOK, oldOperatorOK, memoryValueOK;
public ModèleDeCalculatrice () {
this.oldResultOK = this.oldOperatorOK =this.memoryValueOK = false; }
public doBinaryOperation(char op) {
if (op==‘=’ && oldResultOK && oldOperatorOK) {
if (oldOperator == ‘+’ ) {
oldResult = result = oldResult + result ;
this.notifyAll( // Construit l’argument :
new WhatChanged ( WhatChanged.WC_RESULTAT
, (new Double(result)).toString() ) );
} else if (oldOperator == ‘-’ ) ...
} else if (op == ‘+’) ...
}
protected notifyAll(Object arg) {
this.SetChanged();
this.notifyObservers(arg); }
}
class WhatChanged { ... }
class AfficheurRésultat
extends java.awt.TextField implements java.util.Observer,
java.awt.event.TextListener {
...
public AfficheurRésultat (Observable o) {
o.addObserver(this); //inscription
}
public void update (Observable o,
Object arg) {
// Réception d’un chgt du modèle
WhatChanged wc;
if (arg instanceof WhatChanged ){
wc = (WhatChanged)arg;
if ( wc.mess.equals
(WhatChanged.WC_RESULTAT) )
// Modifier l’affichage
this.setText((String)wc.01);
}
}
}
Cours JAVA / Y.Laborde
11Java : MVC / Exercices
Exercices:1) en supposant que la classe ci-dessous existe,
analysez comment vous pourriez gérer l’ensemble des boutons et de l’indicateur de mémoire à l’aide du modèle.public MemoryPanel extends java.awt.Panel implements java.util.Observer , java.awt.event.ActionListener
2) écrire le code correspondant
Cours JAVA / Y.Laborde
12Java : MVC / La technique du modèle interfacé en strates
L’importance des modèles
La construction d’un modèle est une opération des plus importante dans les applicatifs d’entreprise (importance stratégique, maintenance, développement en
équipes, grande taille, …) car, en définissant les données et les algorithmes propres à l’applicatif, il renferme le cœur de l’application.
Au delà, les vues doivent être également soignées mais elles sont souvent sujettes à transformations. Il est donc important de prévoir dès le départ de l’analyse une base solide permettant facilement de faire évoluer l’applicatif.
Cette base doit elle-même s’appuyer sur un paradigme fort tel que celui du MVC.Or, dans cette technique modulaire de programmation, la base sur laquelle repose l’ensemble du développement n’est autre que le modèle.
C’est pour cela que, dans les développement MVC, les modèles doivent correspondre aux premières préoccupations de l’analyse-conception.
Cours JAVA / Y.Laborde
13Java : MVC / La technique du modèle interfacé en strates
Dérivations successives du modèle(strates)
Pour rendre un modèle à la fois plus souple et plus robuste, il peut être intéressant de le découper. Pour cela, deux techniques (non exclusives) : - le découpage en modèle principal et modèles secondaires (qui donne lieu à une hiérarchie de classes pour les modèles secondaires et où le modèle principal encapsule tous les sous modèles)
- le découpage d’un même modèle en strates (où il s’agit de construire des dérivations successives d’un modèle ; chaque dérivation correspondant à un niveau supplémentaire de fonctionnalités)
Observable
Modèleen stratesObject
ModCalcDeBase
ModCalcPavéNumérique
…
ModCalcOpBinaires
ModCalcMemory
MODELE de base permettant de placer des fonctionnalités
d’ordre générales MODELE répondant à une version élémentaire de la calculatrice sans aucune opération
(afficheur du résultat + pavé numérique)
MODELE répondant à une version avec les opérations binaires
( + , - , * , / , = )
MODELE répondant à une version avec opérations de mémorisation
( indicateur de mémoire , MC , MR , MS , M+ )
abstract class
abstract class
Exemple de modèle
effectivement instancié.
Dans ce cas, la calculatrice
n’aura pas de fonctionnalité de
mémoire.
Cours JAVA / Y.Laborde
14Java : MVC / La technique du modèle interfacé en strates
Interfaçage par strates du modèle
En complément, la technique peut être améliorée par la définition d’interfaces du modèle au niveau de chaque strates.
Cela permettra aux vues, qui devront n’implémenter qu’une interface spécifique du modèle, de n’avoir un regard sur le modèle effectivement instancié qu’au travers d’une interface qui leur est véritablement appropriée.
Observable
Modèleen stratesObject
ModCalcDeBase
ModCalcPavéNumérique
…
ModCalcOpBinaires
ModCalcMemory
abstract class
abstract class
I_ModCalcOpBinaires
I_ModCalcMemory
I_ModCalcPavéNumérique
Interfaces du modèle
implements
public interface I_ModCalcOpBinaires { abstract public doBinaryOperation(char op);}
Exemple de modèle
effectivement instancié.
La vue qui présente les boutons d’opérations binaires conservera une référence au modèle
sous l’aspect de l’interface I_ModCalcOpBinaires.
Cours JAVA / Y.Laborde
15Java : MVC / Exercice
Exercice:
1) Reprenez l’analyse complète de la calculatrice en commençant par l’analyse du modèle (vous mettrez en évidence les différentes strates et interfaces du modèle).
2) Écrivez le code correspondant.