1 1 Université Evry Val d'Essonne Y. Laborde Une calculatrice (sans MVC) fonctionnant sur la base...

18
1 Université Evry Val d'Essonne Y. Laborde Une calculatrice (sans MVC) fonctionnant sur la base d'un modèle en Java

Transcript of 1 1 Université Evry Val d'Essonne Y. Laborde Une calculatrice (sans MVC) fonctionnant sur la base...

Page 1: 1 1 Université Evry Val d'Essonne Y. Laborde Une calculatrice (sans MVC) fonctionnant sur la base d'un modèle en Java.

1Université Evry Val d'EssonneY

. Lab

ord

e

Une calculatrice (sans MVC)

fonctionnant sur la base d'un modèle

en Java

Page 2: 1 1 Université Evry Val d'Essonne Y. Laborde Une calculatrice (sans MVC) fonctionnant sur la base d'un modèle en Java.

2Université Evry Val d'EssonneY

. Lab

ord

e

Principe d'un modèle

class ModelCalc1Variables d'état privées :- hasMemoryStored : boolean - memoryValue : double etc.Méthodes publics :+ isMemoryOperation(String opName) : boolean + doMemoryOperation(String opName) : boolean+ hasMemoryStored() : boolean etc.Méthodes privées :- doMemoryStore() : boolean- doMemoryAdd() : boolean - doMemoryClear() : boolean - doMemoryRecall() : booleanetc.

class ModelCalc1Variables d'état privées :- hasMemoryStored : boolean - memoryValue : double etc.Méthodes publics :+ isMemoryOperation(String opName) : boolean + doMemoryOperation(String opName) : boolean+ hasMemoryStored() : boolean etc.Méthodes privées :- doMemoryStore() : boolean- doMemoryAdd() : boolean - doMemoryClear() : boolean - doMemoryRecall() : booleanetc.

Notations UML utilisées$ = static + = publicƒ = final # = protected

- = private<rien> = package

Notations UML utilisées$ = static + = publicƒ = final # = protected

- = private<rien> = package

➽ un modèle de calculatrice doit :

Gérer l'état courant de la calculatrice en interne

Fournir des méthodes publics qui permettent de piloter la calculatrice depuis une interface graphique

Eventuellement posséder des méthodes privées pour réaliser l'algorithmique consécutive aux demandes d'action via l'interface graphique

➽ un modèle de calculatrice doit :

Gérer l'état courant de la calculatrice en interne

Fournir des méthodes publics qui permettent de piloter la calculatrice depuis une interface graphique

Eventuellement posséder des méthodes privées pour réaliser l'algorithmique consécutive aux demandes d'action via l'interface graphique

Ici, pour ce qui concerne la partie mémoire de la calculatrice

Page 3: 1 1 Université Evry Val d'Essonne Y. Laborde Une calculatrice (sans MVC) fonctionnant sur la base d'un modèle en Java.

3Université Evry Val d'EssonneY

. Lab

ord

e

Exposition du modèle

class ModelCalc1Variables d'état privées :- hasMemoryStored : boolean - memoryValue : double etc.Méthodes publics :+ isMemoryOperation(String opName) : boolean + doMemoryOperation(String opName) : boolean+ hasMemoryStored() : boolean etc.Méthodes privées :- doMemoryStore() : boolean- doMemoryAdd() : boolean - doMemoryClear() : boolean - doMemoryRecall() : booleanetc.

class ModelCalc1Variables d'état privées :- hasMemoryStored : boolean - memoryValue : double etc.Méthodes publics :+ isMemoryOperation(String opName) : boolean + doMemoryOperation(String opName) : boolean+ hasMemoryStored() : boolean etc.Méthodes privées :- doMemoryStore() : boolean- doMemoryAdd() : boolean - doMemoryClear() : boolean - doMemoryRecall() : booleanetc.

➽ pour exposer le modèle, il est bon de définir une interface Java ne montrant que les méthodes publics utiles à son pilotage

➽ pour exposer le modèle, il est bon de définir une interface Java ne montrant que les méthodes publics utiles à son pilotage

interface IModelCalcMéthodes publics :isMemoryOperation(String opName) : boolean doMemoryOperation(String opName) : booleanhasMemoryStored() : boolean etc.

interface IModelCalcMéthodes publics :isMemoryOperation(String opName) : boolean doMemoryOperation(String opName) : booleanhasMemoryStored() : boolean etc.

Ici, pour ce qui concerne la partie mémoire de la calculatrice

En Java, il est fortement conseillé de ne pas utiliser le modificateur public dans les interfaces (il s'entend par défaut)

Page 4: 1 1 Université Evry Val d'Essonne Y. Laborde Une calculatrice (sans MVC) fonctionnant sur la base d'un modèle en Java.

4Université Evry Val d'EssonneY

. Lab

ord

e

➽ le pilotage du modèle est réalisé à travers son interface Java

C'est la seule partie visible depuis les interfaces graphiques

➽ le pilotage du modèle est réalisé à travers son interface Java

C'est la seule partie visible depuis les interfaces graphiques

Pilotage du modèle

ModelCalc1ModelCalc1

PanelAfficheurPanelAfficheur

PanelOperationsPanelOperations

PanelMemoirePanelMemoire

IModelCalcisMemoryOperation(String opName) : boolean doMemoryOperation(String opName) : booleanhasMemoryStored() : boolean etc.

IModelCalcisMemoryOperation(String opName) : boolean doMemoryOperation(String opName) : booleanhasMemoryStored() : boolean etc.

etc.

On entend par "pilotage" toutes les opérations qui permettent de :- Tester si une opération est permise (tests)- Faire évoluer l'état interne du modèle (actions)- Récupérer partiellement l'état interne courant (informations)

ex : imodel.isMemoryOperation("M+")ex : imodel.doMemoryOperation("MC")ex : imodel.hasMemoryStored()

Page 5: 1 1 Université Evry Val d'Essonne Y. Laborde Une calculatrice (sans MVC) fonctionnant sur la base d'un modèle en Java.

5Université Evry Val d'EssonneY

. Lab

ord

e

➽ Plusieurs actions sur la "mémoire" sont possibles. Le modèle les propose au travers d'une unique méthode :

doMemoryOperation(String opName) : boolean

➽ Plusieurs actions sur la "mémoire" sont possibles. Le modèle les propose au travers d'une unique méthode :

doMemoryOperation(String opName) : boolean

Conventions entre modèle et pilote

PanelMemoirePanelMemoireIModelCalcIModelCalc

L'action désirée doit être donnée sous la forme d'un String.

➽ Il faut donc fixer des conventions sur les String à fournir à la méthode.➽ Il faut donc fixer des conventions sur les String à fournir à la méthode.

Ces conventions auront avantage à être présentéesà travers des constantes de classe du modèleet, mieux encore, à être intégrées à l'interface du modèle.

Page 6: 1 1 Université Evry Val d'Essonne Y. Laborde Une calculatrice (sans MVC) fonctionnant sur la base d'un modèle en Java.

6Université Evry Val d'EssonneY

. Lab

ord

e

Conventions entre modèle et piloteinterface IModelCalcConstants

Constantes publics :/** Intitulés des opérations mémoire. * - Additionner la valeur de l'afficheur à la mémoire (M+) * - Placer la valeur de l'afficheur en mémoire (MS) * - Rappeler la mémoire vers l'afficheur (MR) * - Effacer la mémoire (MC) */$ƒ nameOpsMemory : String[] = { "M+", "MS", "MR", "MC" } etc.

interface IModelCalcConstantsConstantes publics :/** Intitulés des opérations mémoire. * - Additionner la valeur de l'afficheur à la mémoire (M+) * - Placer la valeur de l'afficheur en mémoire (MS) * - Rappeler la mémoire vers l'afficheur (MR) * - Effacer la mémoire (MC) */$ƒ nameOpsMemory : String[] = { "M+", "MS", "MR", "MC" } etc.

➽ les conventions sont intégrées dans une interface Java spécifique➽ les conventions sont intégrées dans une interface Java spécifique

interface IModelCalcextends IModelCalcConstants

Méthodes publics :isMemoryOperation(String opName) : boolean doMemoryOperation(String opName) : booleanhasMemoryStored() : boolean etc.

interface IModelCalcextends IModelCalcConstants

Méthodes publics :isMemoryOperation(String opName) : boolean doMemoryOperation(String opName) : booleanhasMemoryStored() : boolean etc.

En Java, il est fortement conseillé de ne pas utiliser le modificateur public dans les interfaces (il s'entend par défaut)

➽ l'interface des méthodes publics du modèle étend celle des conventions

➽ l'interface des méthodes publics du modèle étend celle des conventions

ex: IModelCalcConstants.nameOpsMemory[2] vaut "MR"

Page 7: 1 1 Université Evry Val d'Essonne Y. Laborde Une calculatrice (sans MVC) fonctionnant sur la base d'un modèle en Java.

7Université Evry Val d'EssonneY

. Lab

ord

e

Passons à la vue : le panel "mémoire"

class PanelMemoire extends java.awt.Panel implements java.awt.event.ActionListener

/** Cette classe représente un panel contenant : * - un label indiquant la présence d'une valeur en mémoire, * - un bouton M+ (memory add), * - un bouton MS (memory store), * - un bouton MR (memory read or recall), * - un bouton MC (memory clear). */

class PanelMemoire extends java.awt.Panel implements java.awt.event.ActionListener

/** Cette classe représente un panel contenant : * - un label indiquant la présence d'une valeur en mémoire, * - un bouton M+ (memory add), * - un bouton MS (memory store), * - un bouton MR (memory read or recall), * - un bouton MC (memory clear). */

➽ Il sera implémenté à l'aide de la classe PanelMemoirequi sera également l'ActionListener des boutons mémoire.

➽ Il sera implémenté à l'aide de la classe PanelMemoirequi sera également l'ActionListener des boutons mémoire.

Ce panel a pour responsabilité :- de déclencher les actions mémoire demandées par l'utilisateur vers le modèle,- d'enclencher la mise à jour de l'afficheur en conséquence.

Page 8: 1 1 Université Evry Val d'Essonne Y. Laborde Une calculatrice (sans MVC) fonctionnant sur la base d'un modèle en Java.

8Université Evry Val d'EssonneY

. Lab

ord

e

class PanelMemoireextends Panelimplements ActionListener {

/** Version de la classe. */private static final long serialVersionUID = 1L;

➽ Les ATTRIBUTS statiques de la classe ➽ Les ATTRIBUTS statiques de la classe

➽ Les ATTRIBUTS objets de la classe ➽ Les ATTRIBUTS objets de la classe

/** Attribut pour référer au modèle. */private IModelCalc model;

/** Attribut pour référer à l'afficheur. */private IPanelAfficheur afficheur;

/** Attribut pour référer au label indiquant la présence d'une valeur mémorisée. */private Label displayMemState;

Page 9: 1 1 Université Evry Val d'Essonne Y. Laborde Une calculatrice (sans MVC) fonctionnant sur la base d'un modèle en Java.

9Université Evry Val d'EssonneY

. Lab

ord

e

class PanelMemoireextends Panelimplements ActionListener {

/** Constructeur du panel. * @param model */public PanelMemoire (

IModelCalc model, IPanelAfficheur afficheur ) {

// Conserver le model et l'afficheurthis.model = model;this.afficheur = afficheur;

// Créer et connecter tous les composantsaddAllComponents ();

}

➽ Le CONSTRUCTEUR du panel mémoire ➽ Le CONSTRUCTEUR du panel mémoire

Page 10: 1 1 Université Evry Val d'Essonne Y. Laborde Une calculatrice (sans MVC) fonctionnant sur la base d'un modèle en Java.

10Université Evry Val d'EssonneY

. Lab

ord

e

class PanelMemoireextends Panelimplements ActionListener {

/** Méthode interne ajoutant et organisant les composants dans le panel. */private void addAllComponents () {

// Définir un grid layout de 5 lignes et 2 colonnessetLayout (new GridLayout (5, 1, 2, 2));

// Donner une couleur au panelsetBackground (Color.YELLOW);

// Créer l'indicateur de présence de mémoirethis.displayMemState = new Label ("", Label.CENTER);this.displayMemState.setBackground (Color.BLACK);// L'ajouter au paneladd (this.displayMemState);

// Créer et connecter tous les boutonsfor( String nameBut : IModelCalcConstants.nameOpsMemory ) {

// Créer le bouton (nameBut sera aussi l'action command du bouton)Button b = new Button (nameBut);// L'ajouter au paneladd (b);// Définir le listener du boutonb.addActionListener (this);

}}

➽ La CONSTRUCTION et l'AJOUT des composants du panel mémoire ➽ La CONSTRUCTION et l'AJOUT des composants du panel mémoire

Page 11: 1 1 Université Evry Val d'Essonne Y. Laborde Une calculatrice (sans MVC) fonctionnant sur la base d'un modèle en Java.

11Université Evry Val d'EssonneY

. Lab

ord

e

class PanelMemoireextends Panelimplements ActionListener {

/* (non-Javadoc) * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */public void actionPerformed (ActionEvent e ) {

// Retrouver l'opération à réaliser (actionCommand = texte du bouton)String opName = e.getActionCommand ();

// Vérifier que l'opération soit bien comprise par le modèle (optionnel)if( this.model.isMemoryOperation (opName) ) {

// Lancer l'opération mémoireif( this.model.doMemoryOperation (opName) ) {

// L'opération a maintenant été réalisée

// => l'afficheur peut avoir à changer// (cas de MR)this.afficheur.resetFromModel ();

// => l'indicateur mémoire aussi (cas de MS, M+, MC)if( this.model.hasMemoryStored () ) {

this.displayMemState.setText ("M");} else {

this.displayMemState.setText ("");}

}}

➽ La méthode d'action sur les boutons du panel mémoire ➽ La méthode d'action sur les boutons du panel mémoire

Ici, il faut maintenant mettre à jour tous les affichages qui auront changés du fait de l'opération mémoire réalisée

Ici, ne sachant s'il y a une valeur en mémoire, il faut le demander au modèle.....et mettre l'indicateur à jour en fonction de cela

Page 12: 1 1 Université Evry Val d'Essonne Y. Laborde Une calculatrice (sans MVC) fonctionnant sur la base d'un modèle en Java.

12Université Evry Val d'EssonneY

. Lab

ord

e

Une calculatrice (avec MVC)

fonctionnant sur la base d'un modèle

en Java

Page 13: 1 1 Université Evry Val d'Essonne Y. Laborde Une calculatrice (sans MVC) fonctionnant sur la base d'un modèle en Java.

13Université Evry Val d'EssonneY

. Lab

ord

e

Pourquoi passer au MVC ?

Les composants déclencheurs d'action n'auront plus à se préoccuper de mettre à jour les autres composants.

Les vues devront interpréter des demandes de mise à jour définies conventionnellement par le modèle.

en nous affranchissant de déterminer quels autres composants doivent être mis à jour après une modification du modèle

en nous affranchissant de déterminer quels autres composants doivent être mis à jour après une modification du modèle

en généralisant la notion de vues conformes à un modèle donné

en généralisant la notion de vues conformes à un modèle donné

Le paradigme MVC permet d'aller encore plus loin :Le paradigme MVC permet d'aller encore plus loin :

Le MVC apporte un gain en modularité et doncen sûreté, en maintenance et en longévité des applicatifs.

Page 14: 1 1 Université Evry Val d'Essonne Y. Laborde Une calculatrice (sans MVC) fonctionnant sur la base d'un modèle en Java.

14Université Evry Val d'EssonneY

. Lab

ord

e

Comment ? Principe du MVC

PanelAfficheurPanelAfficheur

PanelOperationsPanelOperations

PanelMemoirePanelMemoireObservable

➽ le modèle renvoie des demandes de mise à jour à toutes les vues inscrites

➽ le modèle renvoie des demandes de mise à jour à toutes les vues inscrites

SEULES les vues qui le désireront se mettrons à jour...

...les autres laisseront passer le message...

Observer

Observer

Observer

ModelCalc1ModelCalc1

IModelCalcIModelCalc

...ainsi, tous les composants auront l'occasion de se mettre à jour.

Par la méthode standardisée dans l'interface Observer :public void update(Observable o, Object arg)

Par des méthodes définies dans l'interface du modèle.

Voir cours MVC

Page 15: 1 1 Université Evry Val d'Essonne Y. Laborde Une calculatrice (sans MVC) fonctionnant sur la base d'un modèle en Java.

15Université Evry Val d'EssonneY

. Lab

ord

e

La mise à jour avec paramètreLe modèle envoie une demande de mise à jour à toutes les vues à l'aide de la méthode :

public void update(Observable o, Object arg)

Le modèle envoie une demande de mise à jour à toutes les vues à l'aide de la méthode :

public void update(Observable o, Object arg)

Voir cours MVC

➽ Pour que les vues comprennent l'argument Object transmis, il faut fixer des conventions sur la nature et le contenu de arg.➽ Pour que les vues comprennent l'argument Object transmis, il faut fixer des conventions sur la nature et le contenu de arg.

Comme précédemment, ces conventions auront avantage à être présentées à travers des constantes de classe du modèleet, mieux encore, à être intégrées à l'interface du modèle.

interface IModelCalcConstantsConstantes publics :/** Conventions de mise à jour des vues par la méthode update * => paramètre Object arg */$ƒ WC_RESULT_HAS_CHANGED : String = "WC_RESULT_HAS_CHANGED"$ƒ WC_MEMORY_HAS_CHANGED : String = "WC_MEMORY_HAS_CHANGED"etc.

interface IModelCalcConstantsConstantes publics :/** Conventions de mise à jour des vues par la méthode update * => paramètre Object arg */$ƒ WC_RESULT_HAS_CHANGED : String = "WC_RESULT_HAS_CHANGED"$ƒ WC_MEMORY_HAS_CHANGED : String = "WC_MEMORY_HAS_CHANGED"etc.

➽ les conventions sont intégrées dans l'interface des constantes du modèle

➽ les conventions sont intégrées dans l'interface des constantes du modèle

Page 16: 1 1 Université Evry Val d'Essonne Y. Laborde Une calculatrice (sans MVC) fonctionnant sur la base d'un modèle en Java.

16Université Evry Val d'EssonneY

. Lab

ord

e

La mise à jour avec paramètre Voir cours MVC

interface IModelCalcConstantsConstantes publics :// Conventions de mise à jour des vues par la méthode update// => le paramètre Object arg est de classe WhatChanged/** Changement du résultat * => l'attribut mess est WC_RESULT_HAS_CHANGED * => l'attribut o1 est un Double contenant le nouveau résultat */static final String WC_RESULT_HAS_CHANGED = "WC_RESULT";/** Changement dans la valeur mémorisée * => l'attribut mess est WC_MEMORY_HAS_CHANGED * => l'attribut o1 est un Boolean contenant la présence d'une valeur en mémoire */static final String WC_MEMORY_HAS_CHANGED = "WC_MEMORY";etc.

interface IModelCalcConstantsConstantes publics :// Conventions de mise à jour des vues par la méthode update// => le paramètre Object arg est de classe WhatChanged/** Changement du résultat * => l'attribut mess est WC_RESULT_HAS_CHANGED * => l'attribut o1 est un Double contenant le nouveau résultat */static final String WC_RESULT_HAS_CHANGED = "WC_RESULT";/** Changement dans la valeur mémorisée * => l'attribut mess est WC_MEMORY_HAS_CHANGED * => l'attribut o1 est un Boolean contenant la présence d'une valeur en mémoire */static final String WC_MEMORY_HAS_CHANGED = "WC_MEMORY";etc.

➽ les conventions sont intégrées dans l'interface des constantes du modèle

➽ les conventions sont intégrées dans l'interface des constantes du modèle

De plus, l'argument Object arg sera l'occasion de transmettre :- la nature du changement survenu dans le modèle- les données utiles pour effectuer la mise à jour côté vue

Et cela, grâce à la classe : WhatChanged (vue en cours)

De plus, l'argument Object arg sera l'occasion de transmettre :- la nature du changement survenu dans le modèle- les données utiles pour effectuer la mise à jour côté vue

Et cela, grâce à la classe : WhatChanged (vue en cours)

Page 17: 1 1 Université Evry Val d'Essonne Y. Laborde Une calculatrice (sans MVC) fonctionnant sur la base d'un modèle en Java.

17Université Evry Val d'EssonneY

. Lab

ord

e

/* @see java.util.Observer#update(Observable o, Object arg) */public void update (Observable o, Object arg){

// Retrouver l'argument WhatChangedif ( arg instanceof WhatChanged ) {

// Secure cast !WhatChange wc = (WhatChanged)arg;// Tester si le message est à prendre en compteif ( wc.mess.equals( IModelCalcWC.WC_MEMORY_HAS_CHANGED ) ) {

// L'indicateur mémoire a changé !if( wc.o1 ) {

this.displayMemState.setText ("M");} else {

this.displayMemState.setText ("");}

}

}

/* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */

public void actionPerformed (ActionEvent e) {

// Retrouver l'opération à réaliser (actionCommand = texte du bouton)String opName = e.getActionCommand ();

// Lancer l'opération mémoirethis.model.doMemoryOperation (opName);

}

➽ RETOUR sur la méthode d'action sur les boutons du panel mémoire ➽ RETOUR sur la méthode d'action sur les boutons du panel mémoire

Maintenant, on se contente de réaliser l'opération mémoire demandée(opName vaut "M+", "MS", "MR" ou " MC")

Ici, l'objet o1 de WhatChanged indique s'il y a une valeur en mémoire...... on met l'indicateur à jour en fonction de cela

Ici, on doit retrouver l'objet WhatChanged......et examiner son message

➽ AJOUT de la méthode de mise à jour du panel mémoire ➽ AJOUT de la méthode de mise à jour du panel mémoire

Page 18: 1 1 Université Evry Val d'Essonne Y. Laborde Une calculatrice (sans MVC) fonctionnant sur la base d'un modèle en Java.

18Université Evry Val d'EssonneY

. Lab

ord

e

Que reste-t-il à faire ? Dériver le modèle de

java.util.Observable Dériver le modèle de

java.util.Observableclass ModelCalc1

extends java.util.Observable

Faire que tous les panels déclarent implémenterjava.util.Observer

Faire que tous les panels déclarent implémenterjava.util.Observer

class PanelMemoireextends Panelimplements ActionListener

, java.util.Observer

Faire que les méthodes du modèle invoquent notifyObservers(Object arg) avec un argument WhatChange

Faire que les méthodes du modèle invoquent notifyObservers(Object arg) avec un argument WhatChange

... setChange(true); ...notifyObservers (

new WhatChange (IModelCalcConstants.

WC_MEMORY_HAS_CHANGED ,new Boolean (hasMemoryStored()) ) );

Faire que tous les panels implémentent la méthodepublic void update(...)

Faire que tous les panels implémentent la méthodepublic void update(...)

Voir diapositive précédente Inscrire les panels auprès des

modèles avec :add(Observer o)

Inscrire les panels auprès des modèles avec :add(Observer o) (dans les panels) : this.model.add (this);