Comparaison des fabriques
Cet article va vous exposer les différences entre :
- Fabrique
- Méthode de création
- Méthode (ou fabrique) de création statique
- Fabrique simple
- Patron de conception Fabrique
- Fabrique abstraite
Vous trouverez des rĂ©fĂ©rences Ă ces termes un peu partout sur Internet. MĂȘme sâils se ressemblent, ils ont tous des significations diffĂ©rentes. Beaucoup ne sâen rendent pas compte, ce qui peut semer la confusion et mener Ă des incomprĂ©hensions.
Essayons donc de dénicher les différences et résolvons ce problÚme une bonne fois pour toutes.
1. Fabrique
Fabrique est un terme ambigu utilisé pour représenter une fonction, méthode ou classe qui est censée produire quelque chose. En général, les fabriques produisent des objets. Elles peuvent également fabriquer des fichiers, des enregistrements de bases de données, etc.
Par exemple, on peut faire rĂ©fĂ©rence Ă nâimporte lequel des Ă©lĂ©ments suivants en lâappelant « fabrique » :
- Une fonction ou mĂ©thode qui crĂ©e lâinterface graphique utilisateur (GUI) dâun programme.
- Une classe qui crée des utilisateurs.
- Une mĂ©thode statique qui appelle un constructeur de classe dâune maniĂšre un peu particuliĂšre.
- Un des patrons de conception de création.
En gĂ©nĂ©ral, lorsque quelquâun parle dâune « fabrique », il est possible de comprendre exactement de quoi il sâagit en sâaidant du contexte. En cas de doute, nâhĂ©sitez pas Ă demander des prĂ©cisions. Il est possible que lâauteur ne connaisse mĂȘme pas ces diffĂ©rences.
2. Méthode de création
La mĂ©thode de crĂ©ation est dĂ©finie dans le livre Refactoring To Patterns comme « une mĂ©thode qui crĂ©e des objets ». Cela signifie que chaque rĂ©sultat du patron de conception fabrique est une « mĂ©thode de crĂ©ation », mais pas lâinverse. Cela signifie Ă©galement que vous pouvez remplacer le terme « mĂ©thode de crĂ©ation » partout oĂč Martin Fowler utilise « fonction factory » (factory method) dans Refactoring ou lorsque Joshua Bloch Ă©crit « mĂ©thode de fabrique statique » dans Java efficace.
En rĂ©alitĂ©, la mĂ©thode de crĂ©ation est juste un emballeur qui englobe un appel au constructeur. Son nom importe peu, tant quâil exprime vos intentions. Il peut toutefois vous aider Ă isoler votre code des modifications apportĂ©es au constructeur. Il peut mĂȘme contenir une certaine logique qui renvoie des objets existants au lieu dâen crĂ©er de nouveaux.
Beaucoup de personnes vont appeler ce genre de mĂ©thodes des « fabriques » juste parce quâelles fabriquent de nouveaux objets. Câest plutĂŽt Ă©vident : la mĂ©thode crĂ©e des objets. Puisque toutes les fabriques crĂ©ent des objets, cette mĂ©thode doit logiquement ĂȘtre une fabrique. Il est donc naturel dâĂȘtre un peu confus lorsque lâon parle du vrai patron de conception Fabrique.
Dans lâexemple suivant, next (suivant) est une mĂ©thode de crĂ©ation :
class Number {
private $value;
public function __construct($value) {
$this->value = $value;
}
public function next() {
return new Number ($this->value + 1);
}
}
3. Méthode de création statique
Une mĂ©thode de crĂ©ation statique est une mĂ©thode de crĂ©ation dĂ©clarĂ©e en static. En dâautres termes, elle peut ĂȘtre appelĂ©e dans une classe et nâa pas besoin dâun objet pour ĂȘtre créée.
Ne soyez donc pas Ă©tonnĂ© lorsque quelquâun appelle une telle mĂ©thode une « mĂ©thode de fabrique statique ». Câest juste une mauvaise habitude. La Fabrique est un patron de conception qui repose sur lâhĂ©ritage. Si vous la rendez static, vous neutralisez lâutilitĂ© du patron, car vous ne pouvez plus lâĂ©tendre dans des sous-classes.
Lorsquâune mĂ©thode de crĂ©ation statique renvoie de nouveaux objets, elle devient un autre constructeur possible.
Cela se révÚle utile si :
-
Vous avez besoin de plusieurs constructeurs diffĂ©rents, mais leurs signatures sont identiques. Par exemple, avoir en mĂȘme temps
Random(int max)etRandom(int min)est impossible en Java, C++, C# et dans bien dâautres langages. Le contournement le plus utilisĂ© consiste Ă crĂ©er plusieurs mĂ©thodes statiques qui appellent le constructeur par dĂ©faut, et Ă affecter les valeurs appropriĂ©es par la suite. -
Vous voulez rĂ©utiliser des objets existants plutĂŽt que dâen instancier de nouveaux (se rĂ©fĂ©rer au patron de conception Singleton). Dans la majoritĂ© des langages de programmation, les constructeurs doivent retourner de nouvelles instances de classes. La mĂ©thode de crĂ©ation statique permet de contourner cette limitation. Ă lâintĂ©rieur de la mĂ©thode statique, votre code va dĂ©cider sâil veut crĂ©er une instance toute fraiche en appelant le constructeur, ou sâil prĂ©fĂšre renvoyer un objet existant depuis le cache.
Dans lâexemple suivant, load (charger) est une mĂ©thode de crĂ©ation statique. Elle fournit une maniĂšre pratique de rĂ©cupĂ©rer les utilisateurs dans une base de donnĂ©es.
class User {
private $id, $name, $email, $phone;
public function __construct($id, $name, $email, $phone) {
$this->id = $id;
$this->name = $name;
$this->email = $email;
$this->phone = $phone;
}
public static function load($id) {
list($id, $name, $email, $phone) = DB::load_data('users', 'id', 'name', 'email', 'phone');
$user = new User($id, $name, $email, $phone);
return $user;
}
}
4. Patron fabrique simple
Le patron Fabrique simple dĂ©crit une classe ayant une mĂ©thode de crĂ©ation qui choisit la classe du produit Ă instancier Ă lâaide dâun gros bloc conditionnel basĂ© sur les paramĂštres de la mĂ©thode, puis la renvoie.
Les fabriques simples sont souvent confondues avec les fabriques générales ou avec un des patrons de création. Dans la majorité des cas, une fabrique simple est une étape intermédiaire pour mettre en place un patron de conception Fabrique ou Fabrique abstraite.
Une fabrique simple est souvent représentée par une unique méthode dans une seule classe. Avec le temps, cette méthode peut devenir trop longue et vous pourriez décider de transférer certaines parties dans des sous-classes. Lorsque vous aurez rencontré cette situation plusieurs fois, vous vous rendrez compte que tout ceci équivaut en fait à un patron de conception fabrique.
Au passage, si vous déclarez une fabrique simple abstract, elle ne se transforme pas en fabrique abstraite comme par magie.
Voici un exemple de fabrique simple :
class UserFactory {
public static function create($type) {
switch ($type) {
case 'user': return new User();
case 'customer': return new Customer();
case 'admin': return new Admin();
default:
throw new Exception('Wrong user type passed.');
}
}
}
5. Patron de conception fabrique
La Fabrique est un patron de crĂ©ation qui dĂ©finit une interface pour crĂ©er des objets, mais permet aux sous-classes de modifier le type de lâobjet qui sera créé.
Si vous voyez une mĂ©thode de crĂ©ation dans une classe de base et des sous-classes qui lâĂ©tendent, il sâagit peut-ĂȘtre dâune fabrique.
abstract class Department {
public abstract function createEmployee($id);
public function fire($id) {
$employee = $this->createEmployee($id);
$employee->paySalary();
$employee->dismiss();
}
}
class ITDepartment extends Department {
public function createEmployee($id) {
return new Programmer($id);
}
}
class AccountingDepartment extends Department {
public function createEmployee($id) {
return new Accountant($id);
}
}
6. Patron fabrique abstraite
La Fabrique Abstraite est un patron de conception de crĂ©ation qui permet de crĂ©er des familles dâobjets apparentĂ©s sans prĂ©ciser leur classe concrĂšte.
Mais que sont « des familles dâobjets »âŻ? Prenons cet ensemble de classes comme exemple : Transport + Moteur + ContrĂŽles. Plusieurs variantes peuvent exister :
Voiture+MoteurCombustion+VolantAvion+MoteurRéaction+Manche
Si votre programme fonctionne sans familles de produits, vous nâavez pas besoin dâune fabrique abstraite.
Je vais me rĂ©pĂ©ter, mais beaucoup confondent la fabrique abstraite avec une classe fabrique toute simple dĂ©clarĂ©e abstract. Ne faites pas cette erreurâŻ!
Postface
Maintenant que vous savez les différencier, posez un regard nouveau sur ces patrons :