Friday, October 5, 2012

Patron : Fabrique (factory)

Le patron Fabrique (Factory en anglais) est un patron de type conception.

Ce patron contient une classe qui fait appel à une fabrique pour créer des objets sans connaitre la classe exacte de ces objets. Pour déterminer la classe exacte, un paramètre est passé lors de l'appel.



Description des classes :

  • Fabrique : la fabrique en charge de créer les objets selon le paramètre recu 
  • Race : classe abstraite 
  • Humain, Orc, Elf : classes fille de Race 
  • Jeu : classe principale qui ne se preocupe pas de quel type de race sont les objets qu'elle manipule 



Dans l'exemple ci-dessous, la classe Jeu fait appel à la classe Fabrique. La classe Jeu ne connais pas les sous-classes de Race.
La responsabilité de créer le bon objet est laissé à la classe Fabrique. Cela fait moins de ligne de code pour la classe Jeu.

Une fois les objets personnagePrincipal, ennemi et ami crées, la classe Jeu traite ces objets comme des objets de type Race.


Jeu.java
public class Jeu {
 
 public static void main(String[] args) {
  Jeu jeu = new Jeu();
  jeu.jouer();
 }
 
 public Jeu() { }
  public void jouer() {
  Fabrique fabrique = new Fabrique();
  
  Race personnagePrincipal = fabrique.getRace("humain");
  action(personnagePrincipal);
  
  Race ennemi = fabrique.getRace("orc");
  action(ennemi);
  
  Race ami = fabrique.getRace("elf");
  action(ami);
 }
 public void action(Race joueur) {
  //on ne se préocupe pas si "joueur" 
  //est un humain ou un orc ou un elf
  joueur.parler();
 }
}
Race.java
public abstract class Race {
  abstract void parler();
}
Humain.java
public class Humain extends Race{
 public Humain() {}
 
 public void parler() {
  System.out.println("Je suis un humain!");
 }
}
Orc.java
public class Orc extends Race{
 public Orc() {}
 
 public void parler() {
  System.out.println("Grrrrrr");
 }
}
Elf.java
public class Elf extends Race{
 public Elf() {}
 
 public void parler() {
  System.out.println("Je suis un elf!");
 }
}
Fabrique.java
public class Fabrique {
 public Fabrique() { }
 
 public Race getRace(String type) {
  Race race;
  
  // ...
  // par exemple: doit faire des trucs 
  // compliqués ici avant la creation d'objet 
  // (verification, initialisation, etc.)
  // ...
  
  if ("humain".equals(type))
   race = new Humain();
  else if ("orc".equals(type))
   race = new Orc();
  else if ("elf".equals(type))
   race = new Elf();
  else
   race = null;
  
  return race;
 }
}



Et sans la Fabrique...

L'exemple est très simple, donc ce n'est pas évident de prouver que sans l'utilisation de ce patron, le code devient plus complexe. Mais je vais essayer.
Voici maintenant le meme code sans la fabrique.
public class NoFactory {

 /**
  * @param args
  */
 public static void main(String[] args) {
  NoFactory noFactory = new NoFactory();
  noFactory.start();
 }
 public NoFactory() { }
 
 public void start() {
  
  // ...
  // par exemple: doit faire des trucs 
  // compliqués ici avant la creation d'objet 
  // (verification, initialisation, etc.)
  // ...
  
  Race personnagePrincipal = new Humain();
  action(personnagePrincipal);
  
  Race ennemi = new Orc();
  action(ennemi);
  
  Elf ami = new Elf();
  action(ami);
 }
 
 public void action(Race joueur) {
  // on ne se préocupe pas si "joueur" 
  // est un humain ou un orc ou un elf
  joueur.parler();
 }
}
Deux choses :

  1. la classe NoFactory doit maintenant s'occuper de faire des trucs compliqués (exemple: verifications, initialisation,etc.) avant la creation des objets 
  2. la classe NoFactory doit connaitre le type exacte des objets. 


J'ai certainement fait des fautes ou écrit des choses pas clair, donc n'hésitez pas laisser un commentaire. Lien Wikipedia : Fabrique

No comments: