Ue conception orientee objet examen juin 2006 - design patt

Exercice : Scrutins et Votes

Q1. Code Java pour la classe VoteOui

public class VoteOui implements Vote { private static final VoteOui INSTANCE = new VoteOui(); private VoteOui() {} public static VoteOui getInstance() { return INSTANCE; } public String toString() { return "OUI"; } public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; return true; } public int hashCode() { return "VoteOui".hashCode(); } }

Q2. Code Java pour la classe VoteNominatif

public class VoteNominatif implements Vote { private String nomCandidat; public VoteNominatif(String nomCandidat) { this.nomCandidat = nomCandidat; } public String toString() { return "Vote pour " + nomCandidat; } public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; VoteNominatif other = (VoteNominatif) o; return nomCandidat.equals(other.nomCandidat); } public int hashCode() { return nomCandidat.hashCode(); } }

Q3. Diagramme UML pour les types Scrutin, ScrutinMajoritaire et ScrutinRelatif

+---------------------+ | Scrutin | +---------------------+ | - votants: Set | | - votesPossibles: Set| | - votes: List | | - estCloture: boolean| +---------------------+ | + vote(votant: Votant)| | + peutVoter(votant: Votant): boolean| | + aVote(votant: Votant)| | + getVainqueur(): Vote| | + depouille()| | + afficheResultat()| | + tauxParticipation(): float| +---------------------+ ^ | +---------------------+ | ScrutinMajoritaire | +---------------------+ | - seuilMajorite: float| +---------------------+ | + getVainqueur(): Vote| +---------------------+ ^ | +---------------------+ | ScrutinRelatif | +---------------------+ | - seuilParticipation: float| +---------------------+ | + getVainqueur(): Vote| +---------------------+

Q4. Intérêt du qualificatif final dans la méthode vote

Le qualificatif final garantit que la méthode vote ne peut pas être redéfinie dans une sous-classe de Scrutin. Cela assure une cohérence stricte du comportement de vote entre tous les scrutins, en empêchant toute modification qui pourrait compromettre la confidentialité des votes (séparation entre votant et vote).

Q5. Code Java des classes Scrutin, ScrutinMajoritaire et ScrutinRelatif

package scrutin; import java.util.*; public abstract class Scrutin { protected Set votants; protected Set votesPossibles; protected List lesVotes; protected boolean estCloture; public Scrutin(Set votants, Set votesPossibles) { this.votants = votants; this.votesPossibles = votesPossibles; this.lesVotes = new ArrayList(); this.estCloture = false; } public final void vote(Votant votant) throws VoteImpossibleException { if (peutVoter(votant)) { Vote vote = votant.vote(votesPossibles); enregistreVote(vote); aVote(votant); } else { throw new VoteImpossibleException(); } } private final void enregistreVote(Vote vote) { lesVotes.add(vote); } public abstract boolean peutVoter(Votant votant); public abstract void aVote(Votant votant); public abstract Vote getVainqueur() throws VoteNonClosException; public abstract void depouille(); public abstract void afficheResultat(); public float tauxParticipation() { return (lesVotes.size() * 100f) / votants.size(); } }
package scrutin; import java.util.*; public class ScrutinMajoritaire extends Scrutin { public ScrutinMajoritaire(Set votants, Set votesPossibles) { super(votants, votesPossibles); } public boolean peutVoter(Votant votant) { return !estCloture && votants.contains(votant); } public void aVote(Votant votant) { votants.remove(votant); } public Vote getVainqueur() throws VoteNonClosException { if (!estCloture) { throw new VoteNonClosException(); } int totalVotes = lesVotes.size(); int seuil = (int) Math.ceil(totalVotes * 0.5f); for (Vote vote : lesVotes) { if (vote != null && !votesPossibles.contains(vote)) { continue; } int score = Collections.frequency(lesVotes, vote); if (score > seuil) { return vote; } } return null; } public void depouille() { estCloture = true; } public void afficheResultat() { for (Vote vote : lesVotes) { int score = Collections.frequency(lesVotes, vote); System.out.println(vote.toString() + " : " + score + " voix"); } } }
package scrutin; import java.util.*; public class ScrutinRelatif extends Scrutin { private float seuilParticipation; public ScrutinRelatif(Set votants, Set votesPossibles, float seuilParticipation) { super(votants, votesPossibles); this.seuilParticipation = seuilParticipation; } public boolean peutVoter(Votant votant) { return !estCloture && votants.contains(votant); } public void aVote(Votant votant) { votants.remove(votant); } public Vote getVainqueur() throws VoteNonClosException { if (!estCloture) { throw new VoteNonClosException(); } int totalVotes = lesVotes.size(); int totalInscrits = votants.size() + lesVotes.size(); int seuil = (int) Math.ceil(totalInscrits * seuilParticipation / 100f); Vote vainqueur = null; int maxScore = 0; for (Vote vote : lesVotes) { if (vote == null || !votesPossibles.contains(vote)) { continue; } int score = Collections.frequency(lesVotes, vote); if (score > maxScore && score >= seuil) { maxScore = score; vainqueur = vote; } } return vainqueur; } public void depouille() { estCloture = true; } public void afficheResultat() { for (Vote vote : lesVotes) { int score = Collections.frequency(lesVotes, vote); System.out.println(vote.toString() + " : " + score + " voix"); } } }

Exercice : Glaces

Q1. Solution avec le design pattern Decorator pour les toppings

+---------------------+ | CoupeGlacee | +---------------------+ | - parfums: List | +---------------------+ | + description(): String| | + cout(): float | +---------------------+ ^ | +---------------------+ | Topping | +---------------------+ | - coupeGlacee: CoupeGlacee| +---------------------+ | + description(): String| | + cout(): float | +---------------------+ ^ | +---------------------+ | ChantillyTopping | +---------------------+ | - surcout: float | +---------------------+ ^ | +---------------------+ | CoulisChocolatTopping| +---------------------+ | - surcout: float | +---------------------+ ^ | +---------------------+ | CoulisFraisesTopping| +---------------------+ | - surcout: float | +---------------------+
package glace; public abstract class Topping implements CoupeGlacee { protected CoupeGlacee coupeGlacee; public Topping(CoupeGlacee coupeGlacee) { this.coupeGlacee = coupeGlacee; } public abstract String description(); public abstract float cout(); }
package glace; public class ChantillyTopping extends Topping { public ChantillyTopping(CoupeGlacee coupeGlacee) { super(coupeGlacee); } public String description() { return coupeGlacee.description() + " chantilly"; } public float cout() { return coupeGlacee.cout() + 0.50f; } }

Q2. Modification de la méthode publieFacture

Non, il n'est pas nécessaire de modifier la méthode publieFacture car elle utilise les méthodes description() et cout() déjà définies dans l'interface CoupeGlacee et implémentées par les classes décoratrices.

Q3. Ligne de code pour créer une coupe avec toppings

CoupeGlacee coupe = new ChantillyTopping(new CoulisChocolatTopping(new TripleChocolat()));

Q4. Refactoring pour gérer les glaces et les boissons uniformément

+---------------------+ | ProduitGlacier | +---------------------+ | + description(): String| | + cout(): float | +---------------------+ ^ | +---------------------+ | CoupeGlacee | +---------------------+ | - parfums: List | +---------------------+ ^ | +---------------------+ | Boisson | +---------------------+ | - type: String | +---------------------+ ^ | +---------------------+ | Topping | +---------------------+ | - produitGlacier: ProduitGlacier| +---------------------+ | + description(): String| | + cout(): float | +---------------------+
package glace; public interface ProduitGlacier { String description(); float cout(); }
package glace; public abstract class Topping implements ProduitGlacier { protected ProduitGlacier produitGlacier; public Topping(ProduitGlacier produitGlacier) { this.produitGlacier = produitGlacier; } public abstract String description(); public abstract float cout(); }
package glace; public class ChantillyTopping extends Topping { public ChantillyTopping(ProduitGlacier produitGlacier) { super(produitGlacier); } public String description() { return produitGlacier.description() + " chantilly"; } public float cout() { return produitGlacier.cout() + 0.50f; } }
package glace; public class Cafe implements ProduitGlacier { private String type; public Cafe(String type) { this.type = type; } public String description() { return "café " + type; } public float cout() { return 1.50f; } }
package glace; public class ChocolatChaud implements ProduitGlacier { public String description() { return "chocolat chaud"; } public float cout() { return 2.00f; } }

FAQ

1. Pourquoi utiliser le pattern Singleton pour les votes OUI, NON et BLANC ?

Le pattern Singleton garantit qu'il n'existe qu'une seule instance de ces votes, ce qui est logique pour des réponses binaires comme OUI ou NON. Cela évite la création de multiples objets identiques et simplifie la gestion des votes.

2. Comment ajouter un nouveau topping sans modifier le code existant ?

Il suffit de créer une nouvelle classe décoratrice qui étend Topping et implémente les méthodes description() et cout(). Par exemple, pour les noisettes caramélisées, il faut créer une classe NoisettesTopping avec son surcoût et description.

3. Quels sont les avantages du refactoring proposé pour les boissons ?

Le refactoring uniformise la gestion des produits glaciers (glaces et boissons) en utilisant une interface commune ProduitGlacier. Cela permet de réutiliser la méthode publieFacture sans modification et facilite l'ajout de nouveaux toppings pour les boissons comme pour les glaces.

Cela peut vous intéresser :

Partagez vos remarques, questions , propositions d'amélioration ou d'autres cours à ajouter dans notre site

Enregistrer un commentaire (0)
Plus récente Plus ancienne