TP2

Thèmes

lecture préalable du Pattern Observateur (note 10 et ce chapitre), du Modèle MVC et du modèle événementiel

 


[Image]Pattern Observateur/Observé

Soit le Pattern Observateur en notation UML selon LA référence : Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides Design Patterns Elements of Reusable Object-Oriented Software Addison-Wesley, 1995. En Java, le paquetage java.util implemente ce Pattern et propose la classe Observable pour Subject et l'interface Observer (lire leur javadoc).

Les participants

Pour cette question, nous souhaitons développer une classe de tests afin de "vérifier" le bon fonctionnement de ce Pattern,

Quelques exemples de "validation", d'assertions

Vérifier que lors d'une notification, TOUS les observateurs ont bien été informés,
Vérifier que les arguments ont bien été transmis,
Vérifier que le notifiant est le bon ...etc ....

Un exemple de test avec BlueJ: vérification qu'un observateur est bien notifié avec le paramètre bien reçu

prémisses et classes retenues:
la classe ConcreteSubject gère une liste de noms, chaque modification de cette liste engendre une notification.
la classe ConcreteObserver se contente, à chaque notification, d'afficher cette liste et de mémoriser l'origine des notifications et les paramètres transmis.
La mémorisation du notifiant et du paramètre transmis utilise deux piles(java.util.Stack<T>), senders et arguments, accessibles de l'"extérieur"

senders : mémorise les émetteurs des notifications
arguments : mémorise les arguments transmis lors d'une notification

ConcreteSubject  list = new ConcreteSubject();       // création d'une liste
ConcreteObserver observer = new ConcreteObserver();  // création d'un observateur
list.addObserver(observer);                          // ajout de cet observateur à la liste
list.insert("il fait beau, ce matin");               // modification de cette liste, l'observateur doit être notifié
// "vérification" : 
assertFalse(observer.senders().empty());                           // la pile senders ne doit pas être vide,
assertEquals(list,observer.senders().pop());                       // est-ce le bon émetteur  ?
assertEquals("il fait beau, ce matin",observer.arguments().pop()); // le paramètre reçu est-il correct ?

Complétez les 3 méthodes de test de la classe "PatternObservateur" et n'oubliez pas de supprimer les fail(); !

AIDE :
  • Compléter test1() en dépilant toutes les piles jusqu'à ce qu'elles soient vides et en vérifiant à chaque fois que l'élément retourné est bien celui attendu.
  • Idem pour test2()
  • Pour test3(), utiliser les 3 méthodes count..., delete..., et delete...s, et vérifier que count... retourne à chaque étape le nombre attendu.
  • Soumettre cette question à JNews après avoir commenté le System.out.println dans ConcreteObserver.update().

[Image]Introduction aux événements de l'AWT

         (paquetage java.awt.event, événements engendrés par une instance de la classe javax.swing.JButton)

En java, la gestion des évènements utilise le pattern Observateur, seuls les noms des méthodes diffèrent, les notifications sont ici engendrées par un changement d'état de l'interface graphique : un clic sur un bouton, un déplacement de souris, etc...
   
la classe Observable "est remplacée par" java.awt.JButton
l'interface Observer "est remplacée par" java.awt.event.ActionListener
la méthode addObserver "est remplacée par" java.awt.event.addActionListener
la méthode  update() "est remplacée par" ActionListener.actionPerformed

A chaque clic, un ou plusieurs observateurs sont réveillés

- le bouton A a 3 observateurs ( jbo1, jbo2 et jbo3)
- le bouton B a 2 observateurs (jbo1 et jbo2)
- le bouton C a 1 observateur (jbo1)

Q2.1) Complétez la classe JButtonObserver, puis la classe AppletteQuestion2 afin d'obtenir le même comportement et les mêmes traces

AIDE :
  • getActionCommand() sur un ActionEvent retourne le nom du composant qui a provoqué cet évènement.

Q2.2) Complétez la classe JMouseObserver pour obtenir le comportement ci-dessous

version 1.5

- le bouton A a 1 observateur de souris (jmo1)
- le bouton B a 1 observateur de souris (jmo2)
- le bouton C a 1 observateur de souris (jmo3)

cette fois

l'interface Observer "est remplacée par" java.awt.event.MouseListener
la méthode addObserver "est remplacée par" java.awt.event.addMouseListener
la méthode  update() "est remplacée par" MouseListener.mouseXXXXXed

implémentant une des méthodes de votre choix : mouseClicked ou mouseEntered ou mouseExited ou mousePressed ou mouseReleased


 

[Image]Le modèle MVC


extraite de http://java.sun.com/blueprints/guidelines/designing_enterprise_applications/introduction/summary/index.html

Selon le "pattern MVC" (Modèle-Vue-Contrôleur)


Q2.1) Développez une application de type calculette à pile, selon le paradigme MVC

L'évaluation d'une expression arithmétique peut être réalisée par l'usage d'une pile d'entiers
   
Par exemple l'expression 3 + 2 engendre la séquence :
                      empiler(3);
                      empiler(2);
                      empiler(depiler()+depiler())
;

de même que l'expression 3 + 2 * 5 correspond à la séquence:
empiler(3);empiler(2);empiler(5);
empiler(depiler()*depiler()); empiler(depiler()+depiler())
Ne pas changer la pile en cas de division par zéro.

L'architecture logicielle induite par l'usage du paradigme MVC nous donne

 


Une des implémentations des piles (issue du tp sur les piles) est installée dans le package tp_pile. Proposer l'implémentation des classes PileModele<T> et Contrôleur

AIDE :
  • Il est conseillé de créer une classe interne par bouton pour ne pas avoir une énorme méthode actionPerformed().
  • Il est également conseillé de soumettre à JNews le code java dès le 1er bouton, puis, une fois correct, de procéder par copier/coller/adapter.

   

Une AppletteCalculette au comportement souhaité

Notez bien qu'un mauvais format de nombre ou une division par zéro ne doivent avoir aucune incidence sur la pile.

Soumettez cette question à JNEWS avant de poursuivre.


Q2.2) Modification de l'application respectant le principe "MVC"

Ajouter cette nouvelle Vue au modèle,

vérifiez que seule la classe Applette est concernée par cet ajout, et que les modifications du source sont mineures.


 public class Vue2 extends JPanel implements Observer
 {
   private JSlider jauge;
   private PileModele<Integer> pile;
  
   public Vue2( PileModele<Integer> pile )
   {
     super();
     this.pile  = pile;
     this.jauge = new JSlider( JSlider.HORIZONTAL, 0, pile.capacite(), 0 );
     this.jauge.setValue( 0 );
     setLayout( new FlowLayout( FlowLayout.CENTER ) );
     this.jauge.setEnabled( false );
     add( this.jauge );
     setBackground( Color.magenta );
     pile.addObserver( this );
   }

   public void update( Observable obs, Object arg )
   {
     jauge.setValue( pile.taille() ); 
   }
 }

Cette modification n'est pas à soumettre à JNEWS.