Wednesday, October 10, 2012

Patron : Monteur (Builder)

Le patron monteur (builder en anglais) est de type création.

Ce patron à pour but de séparer la construction d'un objet complexe de sa representation. Ainsi le meme processus de création peut créer d'autres representations.

En gros, cela veut dire que la classe qui construit l'objet n'est pas la même que la classe qui utilise l'objet.
Voici le diagramme UML provenant de Wikipedia.

Voici le diagramme UML de l'exemple utilisé ci-dessous.


Ici on peut imaginer Asterix qui veut une potion magique. Alors il demande au druide Panoramix de lui préparer.
Asterix n'a aucune idée de la preparation de la potion magique.
Attention, car dans Asterix et le coup du menhir, Panoramix est devenu fou et il a créé une potion qui fait voler les gens.

Voici le code.

Jeu.java
public class Jeu {
 
 public static void main(String[] args) {
  Jeu jeu = new Jeu();
  jeu.jouer();
 }
 
 public Jeu() { }
 
 public void jouer() {
  Recette builderPotionMagique = new RecettePotionMagique();
  Druide panoramix = new Druide(builderPotionMagique);
  
  panoramix.preparerPotion();
  
  Potion potionMagique = panoramix.getPotion();
  System.out.print("Potion magique -> ");
  potionMagique.afficherListeIngredients();
  
  Recette builderPotionVolante = new RecettePotionVolante();
  Druide panoramixFou = new Druide(builderPotionVolante);
  // Asterix et le coup du menhir
  panoramixFou.preparerPotion();
  Potion potionVolante = panoramixFou.getPotion();
  System.out.print("Potion volante -> ");
  potionVolante.afficherListeIngredients();
 }
}
Druide.java
C'est cette classe qui contient les étapes de créations de l'objet Potion.
public class Druide {
 private Recette recette;
 
 public Druide(Recette recette) {
  this.recette = recette;
 }
 
 public Potion getPotion() {
  return recette.getPotion();
 }
 
 public void preparerPotion() {
  recette.ajouterHerbe();
  recette.ajouterHomard();
  recette.ajouterCarotte();
  recette.ajouterSel();
  recette.ajouterPoisson();
 }
}
Recette.java
public abstract class Recette {
 public abstract Potion getPotion();
 public abstract void ajouterHerbe();
 public abstract void ajouterHomard();
 public abstract void ajouterCarotte();
 public abstract void ajouterSel();
 public abstract void ajouterPoisson();
}
RecettePotionMagique.java
Cette classe contient les quantités exactes des ingrédients nécessaires pour faire une potion magique.
public class RecettePotionMagique extends Recette {
 private Potion potion;
 
 public RecettePotionMagique() {
  potion = new Potion();
 }
 
 public Potion getPotion() {
  return potion;
 }
 
 public void ajouterHerbe() {
  potion.setHerbe("3 brindilles");
 }

 public void ajouterHomard() {
  potion.setHomard("1 homard");
 }

 public void ajouterCarotte() {
  potion.setCarotte("2 carottes");
 }

 public void ajouterSel() {
  potion.setSel("3 pincés");
 }

 public void ajouterPoisson() {
  potion.setPoisson("1 poisson frais");
 }
}
RecettePotionVolante.java
public class RecettePotionVolante extends Recette {
 private Potion potion;
 
 public RecettePotionVolante() {
  potion = new Potion();
 }
 
 public Potion getPotion() {
  return potion;
 }
 
 public void ajouterHerbe() {
  potion.setHerbe("1 brindille");
 }

 public void ajouterHomard() {
  potion.setHomard("3 homard");
 }

 public void ajouterCarotte() {
  potion.setCarotte("4 carottes");
 }

 public void ajouterSel() {
  potion.setSel("1 pincés");
 }

 public void ajouterPoisson() {
  potion.setPoisson("2 poissons pas frais");
 }
}
Potion.java
Cette classe est le produit qui sera créé.
public class Potion {
 private String herbe;
 private String homard;
 private String carotte;
 private String sel;
 private String poisson;
 
 public void setHerbe(String herbe) {
  this.herbe = herbe;
 }
 public void setHomard(String homard) {
  this.homard = homard;
 }
 public void setCarotte(String carotte) {
  this.carotte = carotte;
 }
 public void setSel(String sel) {
  this.sel = sel;
 }
 public void setPoisson(String poisson) {
  this.poisson = poisson;
 }
 
 public void afficherListeIngredients() {
  System.out.println("Ingrédients: " + herbe + ", " + homard + ", " + carotte + ", " + sel + ", " + poisson);
 }
}

Ce qui sera affiché :

  • Potion magique -> Ingrédients: 3 brindilles, 1 homard, 2 carottes, 3 pincés, 1 poisson frais 
  • Potion volante -> Ingrédients: 1 brindille, 3 homard, 4 carottes, 1 pincés, 2 poissons pas frais


Imaginons maintenant qu'il existe une autre potion. Et bien il suffit d'ajouter une nouvelle recette.
Par exemple:
public class RecettePotionMiniature extends Recette { ... }


Et si on n'utilise pas le patron builder ?

Et bien les étapes de création de la potion magique seraient dans la class Jeu. La classe Jeu deviendrait longue et aurait trop de responsabilités. La classe Jeu serait plus difficile à maintenir.

No comments: