TP sur AWT et la pattern Observer/Observable

Michel Buffa (buffa@unice.fr), Richard Grin (grin@unice.fr) 20/9/99

Introduction

Java propose en standard une implémentation du pattern Observer/Observable. Ce pattern permet de gèrer facilement l'affichage et la mise à jour de plusieurs vues d'un même objet, concept que vous avez peut-être déjà manipulé avec Excel (un histogramme et un camembert qui bougent lorsqu'on change les valeurs d'une colonne)...

Nous vous proposons d'illustrer ce pattern en écrivant un programme qui fait à peu près la même chose qu'Excel : dessiner des graphiques correspondant à un tableau de valeurs entières, par exemple des histogrammes 2D et des courbes 2D. Lorsque les valeurs entières du tableau changent, les graphiques aussi.

Jouons un peu

Lorsqu'on clique sur le bouton "Nouvelle vue interne" une vue du tableau d'entiers apparaît, comme ceci :

Si on clique à nouveau sur le même bouton, une seconde vue apparaît :

Et ainsi de suite... Si on appuie sur bouton "Random", le tableau d'entier est réinitialisé aléatoirement et les deux vues changent (si vous avez lancé le programme avec l'option -anim, les vues changent également d'elle-mêmes toute les seconde) :

On peut rajouter autant de vues que l'on désire... Si on appuie sur le bouton "Nouvelle vue indépendante", une nouvelle vue sous forme de courbe 2D apparaît, dans une fenêtre cette fois-ci indépendante. Bien évidemment, si on appuie à nouveau sur "Random", toutes les vues changent en même temps. On peut créer autant de vues qu'on veut, la classe TableauEntierEtendu.java correspondant au tableau d'entiers n'en sait jamais rien ! C'est magique !

Travail à faire

On vous fournit la classe TableauEntierEtendu.java : elle décrit un tableau de nombres entiers Observable, et fournit des méthodes pour le remplir aléatoirement et prévenir les différents Observers s'il y en a, que les valeurs ont changées.

On vous fournit aussi la classe abstraite GrapheurTabEntiers.java qui doit être dérivée pour être utilisable. Elle fournit les bases pour pouvoir écrire des classes représentant des vues 2D d'un tableau d'entier. Regardez en particulier la méthode update().

  1. Ecrivez une classe BarGraph.java dérivant de GrapheurTabEntiers et dessinant un histogramme.
  2. Ecrivez un fichier TestObserverObservable.java contenant le programme principal. Vous utiliserez une seule instance de TableauEntierEtendu et vous créerez une instance de BarGraph qui écoute l'instance de TableauEntierEtendu.
  3. La Frame doit contenir dans la zone "Center" (son Layout Manager par défaut est un BorderLayout) l'instance du BarGraph, et dans la zone "South" un bouton poussoir "Random" qui, lorsqu'on clique dessus, ré-initialise aléatoirement le tableau TableauEntierEtendu. L'histogramme doit automatiquement se redessiner si vous avez tout fait comme il faut.
  4. Maintenant, essayez d'avoir plusieurs vues du même TableauEntierEtendu. Ajoutez un bouton "Nouvelle vue". Idem, lorsqu'on clique sur le bouton "Random", toutes les vues doivent bouger.
  5. Ecrivez une classe TableauAnime.java pour que le tableau se réinitialise tout seul toute les secondes (avec un thread). Toutes les vues qui observent ce tableau doivent normalement changer toutes seules chaque seconde.
  6. Telechargez le jar : trieurobservable.jar et lancez java -cp trieurobservable.jar TestTriObservable. Vous verrez un trieur qui trie un tableau et qui est observé par un ou plusieurs GrapheurTabEntier.

  7. Cette fois-ci vous allez vous y prendre autrement que pour le début de ce TP: c'est le trieur qui sera observé par des GrapheurTabEntier, et le trieur trie un tableau "normal" Java (int[]).
    Reprenez la classe Trieur du TP sur les threads et adaptez-la. Le plus simple est d'ajouter les observateurs au Trieur "père" qui a été lancé de l'extérieur de la classe, et les Trieurs "fils" lancés par ce Trieur "père" doivent prévenir les observateurs du Trieur "père". Ca n'est pas très compliqué,  mais vous pouvez vous faciliter la tâche en écrivant un Trieur sans appel récursif.

Correction

Question 1 (une seule vue)
Avec plusieurs vues
Trieur observé