session 2

Transcription

session 2
Examen de POO
Question 1. Quelles parties du code doivent être modifiées pour ajouter un
nouvel observateur ObservateurMessage qui affiche un message à chaque fois que
sa méthode notifier() est invoquée ? Cette classe contient un champ message de
type String initialisé avec un message passé au constructeur de la classe lors de
la création d’une instance. Les observateurs issus de cette nouvelle classe doivent
pouvoir être ajoutés à la classe Bouton et notifiés de la même façon que les
observateurs créés à partir des classes ObservateurCompteur et ObservateurVide.
Juin 2011
Documents autorisés
Durée de l’épreuve : 2 heures
Exercice 1 : Observateurs
Le programme suivant a été écrit par un étudiant qui n’a rien compris aux
concepts de la programmation objet. Cet exercice consiste à réécrire son programme afin qu’il soit plus évolutif.
Question 2. Parmi les 5 principes SOLID, lequel est violé ? Justifiez.
class ObservateurCompteur {
private int cpt;
public ObservateurCompteur() { cpt = 0; }
public void notifier() { cpt++; }
public int getCpt() { return cpt; }
}
Question 4. Implémentez le diagramme de classes que vous avez proposé à la
question 3 en modifiant en conséquence les classes Bouton, ObservateurCompteur
et ObservateurVide de façon à fournir les mêmes services (et conserver les mêmes
comportements). Vous ne devez plus utiliser le mot-clé intanceof et l’opérateur
de transtypage (cast) dans la méthode click() de la classe Bouton.
Question 3. Donnez le diagramme de classes d’une nouvelle organisation qui
respectent les principes SOLID.
Question 5. Dans la nouvelle organisation du code, est-ce que des parties du code
doivent être modifiées pour ajouter l’observateur de type Message ? Proposez une
implémentation de cet observateur.
class ObservateurVide {
public ObservateurVide() { }
public void notifier() { }
}
Exercice 2 : Guerres
class Bouton {
private List observateurs;
Question 1. Qu’affiche le programme suivant ?
public class War {
public static void main (String [] argv) {
List<Perso> persos= new ArrayList<Perso> ();
persos.add (new Mage (1, 7, 8));
persos.add (new Troll (2, 9, 9));
persos.add (new Troll (3, 2, 6));
afficher
persos.get(0).attack (persos.get (1)); afficher
persos.get(1).attack (persos.get (0)); afficher
persos.get(2).attack (persos.get (1)); afficher
}
static void afficher(List<Perso> persos) {
for (Perso p : persos) System.out.print(p+" ");
System.out.println();
}
}
public Bouton() { observateurs = new ArrayList(); }
public void addObservateur(Object obj) { observateurs.add(obj); }
public void click() {
for (Object object : observateurs ) {
if (object instanceof ObservateurVide)
((ObservateurVide)object).notifier();
else if (object instanceof ObservateurCompteur)
((ObservateurCompteur)object).notifier();
}
}
}
1
(persos);
(persos);
(persos);
(persos);
class Mage implements Perso, VisPerso, VisMage, VisTroll
{
public int id, life, mana;
class Troll implements Perso, VisPerso, VisMage, VisTroll
{
public int id, life, force;
public Mage(int i, int l, int m) { id=i; life=l; mana=m; }
public String toString() { return "M"+id+"("+life+","+mana+")"; }
public Troll(int i, int l, int f) { id=i; life=l; force=f; }
public String toString() { return "T"+id+"("+life+","+force+")"; }
public void decLife(int dl) { life=Math.max(life-dl, 0); }
public void decMana(int dm) { mana=Math.max(mana-dm, 0); }
public void decLife (int dl) { life =Math.max(life -dl, 0); }
public void decForce(int df) { force=Math.max(force-df, 0); }
public void attack(Perso p) { p.accept (this); }
public void attack(Perso p) { p.accept(this); }
public void accept(VisPerso vp) {
try {
VisMage vm=(VisMage)vp;
vm.visit(this);
} catch (ClassCastException e) { }
}
public void accept(VisPerso vp) {
try {
VisTroll vt=(VisTroll)vp;
vt.visit(this);
} catch (ClassCastException e) { }
}
public void visit(Mage m) { if (mana > m.mana) m.decMana(1); }
public void visit(Troll t) { t.decForce(mana); }
public void visit(Mage m) { if (force > m.mana) m.decLife(force); }
public void visit(Troll t) { t.decLife(force); }
}
}
interface Perso {
String toString();
void attack(Perso p);
void accept(VisPerso vp);
}
Question 2. Ajoutez un nouveau personnage représenté par la classe Orc. Si un
orc attaque un troll, il lui fait perdre 10 points de vie (champs life). Si un orc
attaque un mage, il lui fait perdre 5 points de vie (champs life). Le constructeur de
la classe Orc prend en paramètre l’identifiant id de l’orc. La méthode toString()
de la classe Orc retourne la chaı̂ne "O" suivie de l’identifiant de l’orc. Le code des
classes de la question précédente n’est pas modifié.
Question 3. Que se passe-t-il si un troll attaque un orc ? Justifiez.
interface VisPerso { }
interface VisMage { public void visit(Mage m); }
interface VisTroll { public void visit(Troll t); }
Question 4. Pourquoi a-t-on utilisé le patron de conception Visiteur ?
Question 5. Pourquoi a-t-on utilisé la version acyclique plutôt que la version
cyclique du patron de conception Visiteur ?
2

Documents pareils