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