L’organisation du code va nous épargner bien des soucis. En utilisant les caractéristiques de la programmation orientée objet, nous pouvons employer certains patrons de conception pour obtenir une meilleure lisibilité, réduire la redondance et créer des abstractions, si nécessaire. L’un de ces patterns est le factory pattern.
Le factory pattern est un type de pattern orienté objet qui suit la méthodologie DRY. Comme son nom l’indique, les instances d’objets sont créées en utilisant une usine pour fabriquer l’objet requis pour nous.
Regardons un exemple très simple d’utilisation du factory pattern pour assembler un objet alligator
. Pour ce faire, nous devons d’abord faire des usines qui créent les pièces alligator
pour nous:
class TailFactory { constructor(props) { this.tailLength = props.tailLength; }};class TorsoFactory { constructor(props) { this.color = props.color; }};class HeadFactory { constructor(props) { this.snoutLenth = props.snoutLenth; }};
Maintenant, nous créons une classe qui agit comme un intermédiaire entre les classes d’usines réelles et l’utilisateur. Appelons cela la ReptilePartFactory
:
class ReptilePartFactory { constructor(type, props) { if(type === "tail") return new TailFactory(props); if(type === "torso") return new TorsoFactory(props); if(type === "head") return new HeadFactory(props); }};
Allons-y et assemblons l’alligator réel maintenant et utilisons la ReptilePartFactory
pour obtenir les pièces requises pour nous:
let alligator = {};let alligatorProps = { tailLength : 2.5, color: "green", snoutLenth: 1};//gets a tail from the tail factoryalligator.tail = new ReptilePartFactory("tail", alligatorProps); //gets a torso from the torso factoryalligator.torso = new ReptilePartFactory("torso", alligatorProps);//gets a head from the head factoryalligator.head = new ReptilePartFactory("head", alligatorProps);
Regardons le modèle ci-dessus, il semble que nous pourrions utiliser la même ReptilePartFactory
pour créer des pièces pour les objets de type alligator. Les usines en arrière-plan n’auraient jamais à connaître la nature de l’objet final.
Donc, l’utilisation du pattern factory nous donne certains avantages :
- Création dynamique d’objets : Il peut être utilisé dans les cas où le type de l’objet est décidé à l’exécution.
- Abstraction : L’utilisateur n’a jamais vraiment besoin d’accéder au constructeur de l’objet réel.
- Réutilisabilité/Maintenance : Les mêmes fabriques peuvent être utilisées pour des objets similaires et cela nous permet d’ajouter/supprimer facilement de nouvelles classes d’objets sans changer beaucoup de code.
Maintenant que nous avons une certaine compréhension du factory pattern, explorons un peu sur l’écriture d’un meilleur code de factory pattern.
L’exemple ci-dessus utilise un if-ladder pour savoir quelle fabrique appeler en fonction de l’entrée utilisateur. C’est une implémentation simple, intuitive et pas très ouverte aux changements. Si nous avons de nouvelles pièces à ajouter plus tard, alors nous devrions perturber le ReptilePartFactory
. C’est une violation des principes SOLID, qui stipule « Les entités logicielles (classes, modules, fonctions, etc.) doivent être ouvertes à l’extension, mais fermées à la modification ».
Pourquoi ne pas stocker les classes de fabrique dans un objet et appeler la fabrique de pièces requise en utilisant la pièce que nous voulons comme clé ? D’abord, nous devrions enregistrer les fabriques, ce serait aussi simple que:
let registeredPartFactories = {};registeredPartFactories = class TailFactory{ ...};registeredPartFactories = class TorsoFactory { ...};registeredPartFactories = class HeadFactory { ...};
Et maintenant, la couche abstraite peut appeler les fabriques comme ceci:
class ReptilePartFactory { constructor(type, props) { return new registeredPartFactories(props); }};
Cette approche est beaucoup plus propre et permet d’étendre nos fabriques sans affecter le code dans le ReptilePartFactory
.
En conclusion
Il y a plusieurs autres patterns orientés objet qui augmentent également la lisibilité et la qualité. Donc avant d’utiliser le factory pattern, vérifiez s’il y a une réelle nécessité. Si vous allez créer des types d’objets similaires à plusieurs reprises et que vous avez également besoin d’une couche pour créer de nouvelles instances en utilisant ces objets tout en fournissant un certain niveau d’abstraction à la logique de création, alors oui – le factory pattern est une bonne option.