Modèles de conception le modèle de méthode d'usine

Dans l'article précédent, nous avons examiné le modèle de fabrique simple. Dans cet article, nous allons maintenant examiner le modèle Factory Method Design. Dans le cas de Simple Factory, il fournit une interface pour créer des objets, tandis que la méthode Factory fait la même chose, mais permet également à une sous-classe de décider de la classe à instancier..

Pour expliquer le modèle de méthode d'usine simple, j'ai utilisé l'exemple de la création d'un objet d'une voiture avec différents types de voitures, à savoir Sedan, SUV, etc. Je vais continuer le même exemple pour expliquer le modèle de méthode d'usine afin d'obtenir un meilleur résultat. idée et continuité.

Le problème

Dans une simple usine, nous créions un objet de la classe auto, mais en réalité, nous créions un objet de la classe auto en fonction du type de voiture que nous avons adopté. Ce fut une bonne étape pour commencer à créer des objets pour une voiture avec différents types.

Auparavant, notre société était limitée à la vente d'une voiture aux États-Unis et elle ne possède qu'un centre de production aux États-Unis. Mais avec le temps, l'entreprise se développe et elle décide de vendre des voitures au Royaume-Uni et de construire un nouveau centre de production au Royaume-Uni..

Dans les deux centres de production, notre ancien code de construction de voitures fonctionne bien, mais pour améliorer la satisfaction de la clientèle, la société décide de modifier certains modèles de voiture, mais uniquement pour les voitures britanniques. A ce stade, notre code pour construire un objet d'une voiture échouera car nous avons besoin de fonctionnalités supplémentaires (attributs) pour un type spécifique de voitures uniquement..

Dans ce cas, nous avons deux options: soit modifier le code actuel (plusieurs conditions si autrement) pour obtenir l'objet de voiture souhaité, soit restructurer nos classes de manière à ne pas requérir de conditions modifiées si dans votre classe et à l'avenir si vous souhaitez ajouter quelques fonctionnalités supplémentaires, mais uniquement pour les types de classe limités.

La première approche à laquelle personne ne voudrait s’adonner, c’est une sorte de patchwork que vous faites dans votre code et non une implémentation réelle. Dans la section suivante, nous verrons comment mettre en œuvre la deuxième approche en utilisant le modèle de conception Méthode d'usine..

La solution

Ce modèle de conception appartient à la catégorie des modèles structurels, il est donc davantage concerné par la façon dont vous structurez vos classes. Passons donc à la solution de notre problème en structurant nos classes de la manière appropriée.

Dans une simple usine, nous n’avions pas utilisé de structure car nous avions besoin d’une seule classe chargée de créer un objet de la voiture. Sur la base du problème actuel, nous devons créer une classe d’usine distincte pour les deux centres de production. Nous voulons donc nous assurer que toutes nos usines suivent le même processus pour créer un objet d’une classe. Par conséquent, nous allons créer une interface que l’usine américaine et britannique mettront en œuvre.

interface carFactory fonction publique buildCar ($ type); 

Notre interface pour les usines est maintenant prête et il est temps de créer des classes de nos usines, à savoir l'usine automobile américaine et britannique..

// Classe d'usine à construire La classe centrale basée aux États-Unis USCarFactory implémente carFactory fonction publique __construct ()  fonction publique buildCar ($ type) $ car = null; switch ($ type) case 'suv': $ car = new USSuvFactory (); Pause; cas 'berline': $ voiture = nouvelle USSedanFactory (); Pause; défaut: $ car = new USSedanFactory (); Pause;  return $ car;  // Classe d'usine pour construire la classe centrale basée au Royaume-Uni UKCarFactory implémente carFactory fonction publique __construct ()  fonction publique buildCar ($ type) $ car = null; switch ($ type) case 'suv': $ car = new UKSuvFactory (); Pause; cas 'berline': $ voiture = nouvelle UKSedanFactory (); Pause; défaut: $ car = new UKSedanFactory (); Pause;  return $ car; 

À ce stade, nos classes d’usine sont prêtes et il est temps de créer notre classe de béton. Mais comme pour l’usine, nous voulons que nos classes concrètes implémentent certaines méthodes requises communes à toutes les classes concrètes..

interface car fonction publique getLocation (); fonction publique getType (); 

Nous avons ajouté des méthodes très basiques à notre classe pour obtenir l'emplacement et le type de voiture. Maintenant nous allons implémenter nos classes concrètes comme ci-dessous.

la classe USSuvFactory implémente car private $ location; private $ carType; fonction publique __construct () $ this-> location = 'US'; $ this-> carType = 'SUV';  fonction publique getLocation () return $ this-> location;  fonction publique getType () return $ this-> carType;  La classe USSedanFactory implémente car private $ location; private $ carType; fonction publique __construct () $ this-> location = 'US'; $ this-> carType = 'Berline';  fonction publique getLocation () return $ this-> location;  fonction publique getType () return $ this-> carType;  La classe UKSuvFactory implémente car private $ location; private $ carType; fonction publique __construct () $ this-> location = 'UK'; $ this-> carType = 'SUV';  fonction publique getLocation () return $ this-> location;  fonction publique getType () return $ this-> carType;  La classe UKSedanFactory implémente car private $ location; private $ carType; fonction publique __construct () $ this-> location = 'UK'; $ this-> carType = 'Berline';  fonction publique getLocation () return $ this-> location;  fonction publique getType () return $ this-> carType; 

Nous en avons terminé avec la mise en œuvre de nos classes de béton, qui sont en réalité un objet de voiture en fonction de l'emplacement et du type de voiture. Ici, il ne reste plus qu'à utiliser cette implémentation pour voir comment elle résout notre problème expliqué ci-dessus.

// US Car Factory $ USFactory = new USCarFactory (); // Modèle SUV basé aux États-Unis $ USSuv = $ USFactory-> buildCar ('suv'); echo $ USSuv-> getLocation (). ' basé '. $ USSuv-> getType (); // Modèle de berline basé aux États-Unis $ USSedan = $ USFactory-> buildCar ('berline'); echo $ USSedan-> getLocation (). ' basé '. $ USSedan-> getType (); // Usine automobile UK $ UKFactory = new UKCarFactory (); // Modèle SUV basé au Royaume-Uni $ UKSuv = $ UKFactory-> buildCar ('suv'); echo $ UKSuv-> getLocation (). ' basé '. $ UKSuv-> getType (); // Modèle de berline basé au Royaume-Uni $ UKSedan = $ UKFactory-> buildCar ('berline'); echo $ UKSedan-> getLocation (). ' basé '. $ UKSedan-> getType ();

Vous pouvez dire que nous avons effectivement créé des objets de tous les types possibles de voiture avec l'emplacement. Nos classes sont bien structurées maintenant, vous n'aurez donc pas de problème à ajouter une nouvelle usine.  

Ajout d'une nouvelle classe d'usine

Imaginons une entreprise qui a décidé de créer un nouveau centre de production en Australie.

Comme nos classes sont bien structurées, il n’y aura plus de problème pour ajouter une nouvelle classe afin de construire un objet auto pour le centre de production australien.. 

// Classe d'usine pour construire la classe centrale basée sur AUS AUSCarFactory implémente carFactory fonction publique __construct ()  fonction publique buildCar ($ type) $ car = null; switch ($ type) case 'suv': $ car = new AUSSuvFactory (); Pause; cas 'berline': $ voiture = nouvelle AUSSedanFactory (); Pause; défaut: $ car = new AUSSedanFactory (); Pause;  return $ car;  // Classes concrètes pour la classe de centre basée sur AUS AUSSuvFactory implémente car private $ location; private $ carType; fonction publique __construct () $ this-> location = 'AUS'; $ this-> carType = 'SUV';  fonction publique getLocation () return $ this-> location;  fonction publique getType () return $ this-> carType;  La classe AUSSedanFactory implémente car private $ location; private $ carType; fonction publique __construct () $ this-> location = 'AUS'; $ this-> carType = 'Berline';  fonction publique getLocation () return $ this-> location;  fonction publique getType () return $ this-> carType;  // AUS Car Factory $ AUSFactory = new AUSCarFactory (); // Modèle SUV basé sur AUS $ AUSSuv = $ AUSFactory-> buildCar ('suv'); echo $ AUSSuv-> getLocation (). ' basé '. $ AUSSuv-> getType (); // Modèle de berline basé sur AUS $ AUSSedan = $ AUSFactory-> buildCar ('berline'); echo $ AUSSedan-> getLocation (). ' basé '. $ AUSSedan-> getType ();

Emballer

Nous avons donc vu comment structurer nos classes de manière à ce qu'elles puissent être étendues sans modification de vos classes de base et du code client. N'hésitez pas à ajouter vos contributions dans la section commentaire ci-dessous ou à me tweeter à @XpertDevelopers.