Vous êtes sur la page 1sur 24

1.

Le problme
Cest un problme trs simple, afin quil puisse tre trait compltement. Il est tir de louvrage Applying UML and Patterns de Craig Larman (et des transparents de Pascal Molli, UHP Nancy). Il sagit dun jeu de ds. Le joueur lance 10 fois 2 ds. Si le total des 2 ds fait 7, il marque 10 points son score. En fin de partie, son score est inscrit dans le tableau des high scores.

2. Lanalyse des besoins (dfinition des fonctionnalits attendues)


2.1. Un premier cas dutilisation Cas Play Description : le joueur lance 10 fois les ds ; chaque fois que le total fait 7, ajout de10pts. Cas View High Score Description : le joueur consulte en lecture seulement les high scores.

Play Player

View High Score

2.2. Un premier diagramme dactivits Sa construction permet de dcrire lorganisation gnrale des traitements et permet de dialoguer avec les clients. On peut complter ce diagramme par des maquettes dcran associes aux diffrentes oprations.

menu [highscore] [start] Start turn=0 Roll Dice turn++ [true] Turn<10 [false] Update highscore [exit]

view Highscore

Il doit exister une certaine cohrence entre ces diagrammes. On peut vrifier que tous les cas se retrouvent quelque part dans le diagramme dactivits.

menu [highscore] view Highscore [start] Start turn=0 Roll Dice turn++ [true] Turn<1 [false] Update highscore [exit]

Play Player

View High Score

3. Lanalyse (dfinition des classes du domaine et de leur dynamique)


3.1. Un premier diagramme de collaboration Il permet de visualiser des objets, leurs relations et lordonnancement des appels de messages.
2: r1=roll( ) 1: play( ) game : DiceGame toto : Player 3: r2=roll( ) d2 : Die

d1 : Die

3.2. Un premier diagramme de classes On complte les classes et on reprsente leurs associations statiques et dynamiques ; on dfinit les attributs des classes et les cardinalits des associations.
Player name : String score : int = 0; play( ) 1 Plays 1 DiceGame 1 Includes 1 Rolls 2 Die faceValue : int = 1 roll( ) 2

1 Scoring 1 HighScore

Ici aussi il faut vrifier la cohrence des diagrammes.


Player d1 : Die 2: r1=roll( ) 1: play( ) game : Dice Game 3: r2=roll( ) d2 : Die toto : Player name : String score : int = 0; 1 play() 1 Plays 1 DiceGame 1 1 Includes Rolls 2 Die faceValue : int = 1 roll() 2

Scoring 1 HighScore

3.3. Des diagramme de squence Ils modlisent la dynamique (~ comme diagrammes de collaboration) en se focalisant sur lenchanement des messages.
: DiceGame : Player d1 : Die d2 : Die

1: play( )

2: roll( ) 3: roll( )

On peut aller plus loin en modlisant la cration des objets en dbut de partie. A noter que le joueur ( :Player) nest cr quau dmarrage de la partie. Cest un choix qui dcoule du diagramme dactivit. On aurait tout aussi bien pu crer le joueur au moment ou lon cre le jeu. Le petit avantage est que lon peut changer de nom entre 2 parties
: RealPlayer : DiceGame d1 : Die d2 : Die : Player

1: DiceGame( )

2: Die( )

3: Die( )

4: start( ) 5: Player(String)

3.4. Un diagramme dtats Il a pour objet de dterminer les tats et transitions dtat dun objet. Ici le diagramme dtats dune partie (diceGame).
cancel Start game Ready to play start Player ready entry: get player name

Quit

Cancel

play roll dices[ turn<10 ]

[ turn>=10 ]

In progress entry: turn++

On dtecte certaines incohrences.

Cancel ? menu [highscore] [start] view Highscore [exit]


Start game
Ready to play

Cancel start
Player ready entry: get player name

Start turn=0 Roll Dice turn++

Quit Cancel

play

roll dices[ turn<10 ]

[true] Turn<10 [false] Update highscore

[ turn>=10 ]

In progress entry: turn++

Cancel ?

Ces incohrences mises en vidence par le diagramme dtats conduisent modifier les diagrammes prcdents ainsi que les maquettes dcrans envisages lors de lanalyse des besoins.

menu [highscore] [start]


Start turn=0 Roll Dice turn++

[exit]

view Highscore

cancel

cancel

[true] Turn<1 [false] Update highscore

3.5. Le problme de larrt de lanalyse Il faut se demander si les cas dutilisation sont couverts correctement par lanalyse. La rponse est plutt ngative.

menu

[highscore]

[start] Start turn=0 Roll Dice

[exit]

Play Player

view Highscore

turn++
View High Score [true] Turn<10 [false]

Partiellement trait Pas trait

Update highscore

Il faut donc reprendre les schmas pour grer le highscore (cration et mise jour).

: RealPlayer 1: DiceGame( )

: DiceGame 2: Die( )

d1 : Die

d2 : Die

: HighScore

3: Die( ) 4: Highscore( )

: DiceGame

: Player

d1 : Die

d2 : Die

new : Entry

: HighScore

1: Player(String)

2: play( ) 3: roll( ) 4: roll( ) 5: Entry(name:String,score:int)

6: add(Entry)

Player name : String score : int = 0 play() Player() 1 1 Plays

Rolls 2

Die faceValue : int = 1 roll() Die() 2 1

DiceGame DiceGame() start() 1 Scoring 1 HighScore Highscore() add() 1 0..* 1

Includes

Entry name:String score:int Entry(name:String,score:int)()

Lanalyse des cas est peu prs complte. On pourrait encore raffiner un peu la dynamique du cancel et les diagrammes de squence du jeu. Passons la phase de conception de la solution.

4. La conception
4.1 Larchitecture gnrale On fait le choix dune architecture en couches (pattern architectural Layer vu en cours) comportant trs classiquement 3 couches.

Prsentation

Application
Play View High Score

Persistance

Fichier ou BDD

Il correspond cette architecture des paquetages et des dpendances entre paquetages. Le paquetage Util regroupe les services qui ne se rattachent pas clairement aux niveaux.
<<layer>> UI

<<layer>> Core

<<subsystem>> Util

<<layer>> Persist

4.2. Conception du niveau applicatif Core On cherche appliquer diffrents design patterns permettant de mieux structurer les classes.

a) le pattern singleton Assure quune classe une instance unique quelle garde dans une variable de classe (static uniqueInstance) et donne un point daccs depuis la classe cette instance (mthode de classe static Instance() ou getInstance()).

Conception
HighScore $ hs : HighScore = null Highscore() add() load() save() 1 0..*

Analyse
Player name : String 1 score : int = 0; play() Player() 1 Plays Rolls 2 Die faceValue : int = 1 roll() Die() 2

Entry name:String score:int = 0 Entry(name:String,score:int)()

DiceGame $ dg = null DiceGame() getInstance() start() 2

Singleton...

1 DiceGame DiceGame() start()


1 -player Play er name : String score : int = 0 Player() display()

Includes 1

-dies

1 Scoring 1 HighScore Highscore() 1 0..* add() Entry name:String score:int = 0 Entry(name:String,score:int)()

Die faceValue : int = 1 roll() Die() display()

Sont galement ajoutes des mthodes pour sauvegarder les high score (load, save) et pour afficher les ds et joueurs (display). b) le pattern observer Un objet (le sujet) est li plusieurs objets (les observateurs ou observers) pas ncessairement connus la cration du programme. Toute modification est automatiquement rpercute (notifie) tous les observateurs.

Ici, les ds et les joueurs sont les sujets (classe Observable) et les vues sur les ds et sur les joueurs sont les observateurs (interface Observer).
Observable changed : boolean = false Observable() addObserver() deleteObserver() notifyObservers() deleteObservers() setChanged() clearChanged() hasChanged() countObservers() <<Interface>> Observer 0..* update(o : Observable, arg : Object) : void

Panel Panel()

Die DieView faceValue : int = 1 roll() Die() display() PlayerView PlayerView(player : Player) update(o : Observable, arg : Object) : void DieView(die : Die) update(o : Observable, arg : Object) : void

Player name : String score : int = 0; Player() display()

Les vues sont les lments daffichage des objets. Ils doivent voluer ds que lobjet observ change. Do le recours au pattern Observer avec notifyObservers et update(). Les vues sont des paneaux (Panel) au sens de linterface utilisateur (ici awt de Java), cest dire une zone dune fentre.

La mise en place de cette structure ncessite les changes suivants :


classe de linterface utilisateur 1: display( ) :Player : PlayerView : Die : DieView

2: PlayerView(Player)

3: addObserver(Observer)

4: return component

5: display()

6: DieView(Die) 7: addObserver(Observer)

8: return component

et la propagation dun vnement (ici une nouvelle valeur pour un d) ncessite :


: Die : Randomizer 1: getValue( ) 2: setValue(int) 3: notifyObservers( ) : DieView

4: update(Observable, Object)

o Randomizer est une classe qui rend une valeur au hasard (pour le tirage du d entre 1 et 6). Il faut noter que les interfaces utilisateurs (comme awt en Java) se chargent de propager les vnements sur les lments dinterface (bouton appuy, valeur saisie, clic ou dplacement de souris, fermeture de fentre, ...) vers les classes applicatives. Le pattern Observer fait le travail oppos : il notifie les changements dtat des classes applicatives aux lments de linterface utilisateur. 4.3. Conception du niveau interface utilisateur UI Il faut dfinir les fentres graphiques (forms) contenant ventuellement les panneaux vues. Toutes les forms hritent de la classe awt Frame.

Frame
(from awt)

PlayerForm ok_action() cancel_action() PlayerForm() 0..1 MainForm HighScoreForm ok_action() quit_action() start_action() high_action() MainForm() RollForm 0..1 roll_action() cancel_action() RollForm() 1 PlayerView HighScoreView update() <<Interface>> Observer PlayerView() update() 2 DieView DieView() update()

update()

Mise en place de linterface utilisateur et dmarrage du jeu :

: RealPlayer

: DiceGame

: MainForm

: PlayerForm

:Player

: RollForm

1: getInstance( )

2: MainForm( )

3: start_action( ) 4: PlayerForm( )

5: ok_action( ) 6: start( String playerName) 7: Player(String) 8: RollForm( )

9: display( ) + diagramme prcdent de mise en place

Amlioration du dcouplage UI / Core : introduction dun Interface Displayable.


HighScore $ hs : HighScore = null Highscore() add() load() save() Entry name:String ; score:int ; 1 0..* Entry(name:String,score:int)()

<<Interface>> Displayable display() 2 2 Die faceValue : int = 1 roll() Die() display() setValue()

DiceGame $ dg = null DiceGame() getInstance() start() -dies 1

Singleton...

-player Player name : String score : int = 0; Player() display()

Do larchitecture en couche avec des interfaces et classes abstraites de dcouplage :

RollForm

Classes techniques UI

DieView

2 +theDieView

roll_action() cancel_action() RollForm()

+thePlayerView PlayerView 1 PlayerView() update()

DieView() update()

Interface et classes abstraite de dcouplage

<<Interface>> Displayable

Observable 0..*

<<Interface>> Observer

Classes applicatives Core

Die faceValue : int = 1 roll() Die() display() setValue()

Player name : String; score : int = 0; Player() display()

4.4 Le paquetage Util Il comprend la classe Randomizer qui utilise la classe Java Random. Encore un singleton !
Singleton : Player : Die : Randomizer : Random

1: roll( )

2: getInstance( ) 3: Randomizer( )

Randomizer getInstance() getValue() 4: Random( )

Random Singleton !

Random() nextInt()

5: getValue( )

6: nextInt(int)

4.5 Le niveau persistance Persist Il contient les classes techniques de persistance. Lobjectif est dassurer l indpendance Core/Persist afin de pouvoir utiliser plusieurs types de persistance.

Par exemple, la srialisation (persistance dobjets lis dans un fichier) et lutilisation dune base de donnes relationnelle (via JDBC). Pour cela, on fait appel au pattern Factory. Ce pattern sert quand une classe peut crer des objets (ProduitConcret) de diffrentes classes. Une interface unique (Fabrication) est implante par diffrentes classes concrtes pour chaque type dobjet crer (FabricationConcrte). La classe qui veut crer les objets peut ne travailler quavec les interfaces.
Produit Fabrication Fabriquer() UneOperation() produit=Fabriquer()

FabricationConcrte ProduitConcret Fabriquer()

return new ProduitConcret()

Ici, les fabriques concrtes crent un highscore srialisable ou un highscore jdbc.


HighScore

Produit abstrait

$ hs : HighScore = null Highscore( ) add() load() save()

Produit

concret
Fabrique concrte

HighScoreJDB C Highscore() load() save()

HighScoreS $ filenamer : String = "/tmp/high.score" Highscore() load() save()

JdbcKit makeKit()

SrKit makeKit()

Fabrique abstraite

PersistKit makeKit()

La dynamique de la couche de persistance est donc la suivante :

: RealPlayer

: DiceGame

: SrKit

: HighScoreSr

1: SrKit( ) 2: getInstance( ) 3: DiceGame( )

Attention! DiceGame voit SrKit comme un PersistKit et HighScoreSr comme un HighScore

4: makeKit( )

5: HighScoreSr( ) 6: load( )

Seul le Realplayer sait qu'il veut utiliser un SrKit ! DiceGame non !

7: quit( )

8: getInstance( ) 9: save( )

Dans le cas srialisable, la persistance se propage automatiquement de lobjet racine (highscore) tous les objets dpendants (entries).
class HighScoreSr extends HighScore implements Serializable { ... public void save() throws Exception { FileOutputStream ostream = new FileOutputStream(filename); ObjectOutputStream p = new ObjectOutputStream(ostream); p.writeObject(this); // ecrit le highscore et toutes les entries p.flush(); ostream.close(); // ferme le fichier de serialisation } public void load() throws Exception { FileInputStream istream = new FileInputStream(filename); ObjectInputStream q = new ObjectInputStream(istream); HighScoreSr hsr = (HighScoreSr)q.readObject(); }

Dans le cas de JDBC, une table doit tre cre dans un SGBD relationnel. A la cration de HighScoreJDBC il y a connexion au SGBD via JDBC. Un save consiste faire des inserts pour chaque entry . Un load consiste faire un Select * from ..., parcourir le rsultat et crer les objets entry correspondants.

public class HighScoreJDBC extends HighScore { public static final String url="jdbc:odbc:dice"; Connection con=null; public HighScoreJDBC() { try { //charge le driver JDBC Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); con=DriverManager.getConnection(url, "toto",""); } catch (Exception e) { e.printStackTrace(); new Error("Cannot access Database at"+url); } hs=this; // enregistrement de linstance unique! this.load(); } public void load() { try { Statement select=con.createStatement(); ResultSet result=select.executeQuery ("SELECT Name,Score FROM HighScore"); while (result.next()) { this.add(new Entry(result.getString(1), result.getInt(2))); } } catch (Exception e) { e.printStackTrace(); } public void save() { try { for (Enumeration e = this.elements() ; e.hasMoreElements() ;) { Entry entry=(Entry)e.nextElement(); Statement s=con.createStatement(); s.executeUpdate("INSERT INTO HighScore (Name,Score)"+ "VALUES('"+entry.getName()+"',"+ entry.getScore()+")"); } } catch (Exception e) { e.printStackTrace(); } }

Remarque : highscore est une collection dentres (do le this.elements()). 4.6 Le diagramme de composants

Displayable DicePersist HighScore PersistKit Observer DiceSystem Observable

Dice Vizualization

Ralisation dun interface Utilisation dun interface

Randomizer Random system

Un interface

4.7 Le diagramme de dploiement


JBDC Connection Save/load the highscore

Game Computer SGBD computer

Play the game

File System

a file system maybe a Remote

5. Limplantation
5.1. Gnration du code Traduire la conception dtaille dans un langage objets (Java, C++, Smalltalk, ...) ou non (C, VB, ...). Cest videmment plus direct vers un langage objets ! Exemple : Traduction en Java des composants :
<<Interface>> Displayable display()

Observable (from util)

package Core; import import import import Util.Randomizer; UI.DieView; java.util.*; java.awt.Component;

Die faceValue : int = 1 roll() : int Die() display() : java.awt.Component setValue(value : int) : void getValue() : int

public class Die extends Observable implements Displayable { private int faceValue = 1; public int roll() { setValue(Randomizer.getInstance(). getValue()); return getValue(); } public java.awt.Component display() { Component c=new DieView(this); this.addObserver((Observer)c); return c; } public void setValue(int value) { faceValue=value; this.setChanged(); this.notifyObservers(); } public int getValue() {

Traduction en Java des associations :

HighScore
(from Core)

$ hs : HighScore = null Highscore() add() load() save() getInstance() 1 0..*

Entry
(from Core)

name:String; score:int ; Entry(name:String,score:int)()

Les environnements de conception (ateliers) UML donnent des outils de gnration de code (forward engineering), de rtro conception partir du code (reverse engineering). La combinaison des deux tant appele round trip engineering. Lobjectif est dassurer en permanence la cohrence de lanalyse, de la conception et du code. Un exemple de gnration :
Die Player
(from Core) (from Core)

package Core; import java.util.*; import java.awt.Component; import UI.HighScoreView; public abstract class HighScore extends Observable implements java.io.Serializable, Displayable { protected static HighScore hs = null; public Vector entries=new Vector(); public void add(Entry entry) { entries.addElement(entry); this.setChanged(); this.notifyObservers(); } public Enumeration elements() { return entries.elements(); } public abstract void load(); public abstract void save(); public Component display() { // implantation de Displayable Component c=new HighScoreView(this); this.addObserver((java.util.Observer)c); return c; } public static HighScore getInstance() { if (hs==null) new Error("No Persist Kit declared");

faceValue : int = 1 roll() Die() display() setValue() -dies 2

name : String score : int = 0 Player() display() -thePlayer

+theDiceGame DiceGame
(from Core)

$ dg = null DiceGame() getInstance() start() quit()

// Source file: c:/UML/Core/DiceGame.java package Core; public class DiceGame { private static int dg = null; private Die dies[]; private Player thePlayer; DiceGame() {} /** @roseuid 37F877B3027B */ private DiceGame() {} /** @roseuid 3802F61403A0 */ public void getInstance() {} /** @roseuid 37F8781A014D */ public void start() {} /** @roseuid 38074E7F0158 */

Un exemple de rtro conception :


Observable
(from util)

Vector
(from util)

Die faceValue : int = 1 roll() Die() display() setValue() getValue() -dies[]

+entries

Player score : int = 0 turn : int = 0 WIN_NUMBER : int = 7 WIN_SCORE : int = 10

Entry score : int Entry() getName() getScore() toString()

HighScore HighScore() add() elements() load() save() display() #$hs getInstance()

Player() die1() DiceGame die2() -thePlayer play() display() DiceGame() getName() getInstance() getScore() start() getTurn() getDie() setTurn() getPlayer() -$dg setScore()

-name

-name String

(from lang)

Rien nest possible pour les aspects dynamiques. Il sagit donc dune aide limite. 5.2. Dernires amliorations A la fin de lanalyse on avait signal des manques du ct de la dynamique du cancel et de la gestion du jeu qui tait dfinie par :
: DiceGame : Player d1 : Die d2 : Die new : Entry : HighScore

1: Player(String)

2: play( ) 3: roll( ) 4: roll( ) 5: Entry(name:String,score:int)

6: add(Entry)

Rien nayant t fait, il faut reprendre ces aspects en liaison avec la conception dtaille actuelle. Le schma prcdent ne gre pas les 10 tours de jeu et la fin du jeu. La version remanie doit correspondre au fonctionnement ci dessous.

Soit en termes de diagramme de squences :


: RollForm : Player : Die : Die

1: actionPerformed(ActionEvent)

2: rollAction( )

3: getTurn( ) 4: [turn<10] play( ) 5: setValue(int) 6: setValue(int) 7: setTurn(int)

6. Les tests
Il faut dabord tester toutes les mthodes, classe par classe (tests unitaires). Puis il faut tester les composants (tests dintgration), et enfin, le systme tout entier (test dacceptation au regard des use case et du diagramme dactivits initial dfinissant les besoins).

Vis vis des cas dutilisation et de leur description tout semble correct. Vis vis du diagramme dactivits, il faut tester tous les chemins possibles. Regardons ce point.

menu [highscore] view Highscore [start]


Start turn=0 Roll Dice turn++

[exit]

cancel

cancel

[true] Turn<1 [false] Update highscore

Le chemin normal start, roll*, highscore, exit marche correctement. Par contre le chemin highscore, exit plante ! Il sagit dun problme de (mauvaise) conception. En effet, cest DiceGame qui cre Highscore lors du start. Il faut corriger ! Enfin, le chemin highscore, start, roll* doit voir le highscore (dont la fentre est dj ouverte) voluer dynamiquement si le MVC fonctionne correctement. Cest bon !

7. Conclusions
Lanalyse des besoins a utilis cas dutilisations + descriptions, diagramme d activits, prototypage de linterface utilisateur. Lanalyse a utilis pour la dynamique : les diagrammes de collaborations, squences, tats, pour la statique : les diagrammes de classes. La conception a utilis : le pattern architectural Layer les diagrammes de paquetages, de composants, de dploiement, les design patterns Singleton, Observer, Factory, des classes techniques pour la persistance et linterface utilisateur. La ralisation a utilis les outils de gnration et de rtro conception. Il est indispensable de mettre jour la documentation danalyse et de conception. Les tests ont utilis les cas dutilisation (couverture des fonctionnalits) et le diagramme dactivit (conformit). Bien entendu sur des grosses applications les dmarches de test sont plus complexes (intgration, non rgression, ...).

UML permet davoir plusieurs points de vue chaque tape et de rflchir en termes de couverture et de cohrence. Le travail est facilit avec un atelier UML.

Play Pyr l e a

Cohrence !! Couverture !!
Fd eeae nBvrg i [ no coffee ] [n ca] oo l [f u dc f e] on o e [on ca] fud o l P tC fe nFe u o ei t r l i Ad We o Rsro d ar t ee r t vi G Cs e u t p Gt Cn o Ca e a f o l PutFilterinMachine

DicePersist HighScore

DiceSystem

Displayable

Dice Vizualization

Observable PersistKit Observer

ViewHighScore

Randomizer
JBDC Connection Save/loadthe highscore

Rno adm system


GameComputer SGBD computer

Playthe gm ae File System

MaybeaRemote a file system

d :D 1 e i
T r o M cn un n ahe i

Pyr ae l
^oe o u O cf Pt r n e .n T B w oe r Ce e f

2r =o( :1 r l)
Rolls Die f c V l ei t 1 a e au :n=

(mUeCs Vw r s ae e ) f o i

1pa () : ly gm :De ae c i Ge a m 3r =o( :2 r l)

n m :Si g ae t r n so :n=0 1 cr it ; e
lightgoesout

2 r( o l) 1

py a( l) 1
P uC f e or o e Dk ee g r Bvr e n a i

d :D 2 e i
I cu e nl d s 1 D ae cm e iG 11 Scoring 1 HighScore
/ Sat g m tr a e Ready to play cancel

Py as l

Mm :Pyr o o ae l

vue architecturale
:DiceGame : Pa e lyr d1 : Die d2:Die 1: play( ) 2: roll( ) 3: roll( )

vue fonctionnelle

start

Player ready entry: get player name

Quit play rolldices[turn<10]

Cancel

[ turn>=10 ]

In progress entry: turn++

vue statique

vue comportementale

UML permet de documenter les choix danalyse et de conception. Grce au processus de dveloppement matris, le produit est conforme ce qui tait prvu au dpart. Grce aux patterns, le produit est volutif (on peut facilement modifier linterface ou la persistance). Grce Java, le produit est portable (systme, SGBD). ANNEXE : structuration finale de lapplication
Observable
(from util)

Vector
(from util)

String
(from lang)

+entries

-name -name

Core

Die f aceValue : int = 1 roll() Die() display() setValue() getValue()

HighScore HighScore() add() elements() load() save() display() getInstance()

#$hs

Player score : int = 0 turn : int = 0 WIN_NUMBER : int = 7 WIN_SCORE : int = 10 Player() die1() die2() play() display() getName() getScore() getTurn() setTurn() setScore()

Entry score : int Entry() getName() getScore() toString()

-dies[] -thePlayer

DiceGame DiceGame() getInstance() start() getDie() getPlayer() -$dg <<Interface>> Displayable display()

UI (1)

ActionListener
(from event)

Frame
(from awt)

HighScoreForm actionPerformed() HighScoreForm() closeAction() -hf -mf MainForm -tf +m_MainForm RollForm actionPerformed() rollAction() cancelAction() RollForm() -close -quit +ok +cancel -start Button
(from awt)

TextField
(from awt)

-rf

actionPerformed() quitAction() startAction() +m_MainForm highAction() MainForm() -pf getInstance() -$mf

PlayerForm actionPerformed() okAction() cancelAction() PlayerForm()

-high -ok -cancel

HighScoreForm

RollForm actionPerformed() rollAction() cancelAction() RollForm() +ok Button


(from awt)

UI (2)

actionPerformed() HighScoreForm() closeAction() +m_HighScoreForm -close

+cancel

-m_RollForm

+m_RollForm

-hv HighScoreView HighScoreView() update()

+theDieView[] DieView DieView() update()

+thePlayerView -turnLabel -nameLabel -scoreLabel -l Label


(from awt)

PlayerView PlayerView() update()

-l List
(from awt)

Observer
(from util)

Persist
Serializabl
(from io) e

DiceGam
(from Core) e

Entr HighScor e (from Core) +entrie (from util) HighScore( s add() ) elements( #$hs load() ) save( display( ) getInstance ) () Vector
(from Core) y

PersistKi t #$pk PersistKit( getInstance ) makeKit( () )

DiceGame( -$dg getInstance ) start( () getDie( ) getPlayer( ) )

score : int Entry( getName( ) getScore( ) toString( ) )

JdbcKit JdbcKit( makeKit( ) ) SrKit makeKit( SrKit() )

HighScoreJDB C HighScoreJDBC () load() save( )

HighScoreS r load() save( HighScoreSr ) ()

Util

Randomizer getInstance() getValue() Randomizer()

-random

Random
(from util)

-$r