Modele de proiectare Modelul metodei fabricii

În articolul precedent am trecut prin modelul simplu de fabrică. Acum, în acest articol vom examina modelul de fabricare a metodei de fabricare. În cazul Simple Factory, acesta oferă o interfață pentru a crea obiecte, în timp ce metoda Factory face același lucru, dar în plus permite unei subclase să ia o decizie asupra clasei pe care să o instanți.

Pentru explicarea modelului Simple Factory Method, am folosit exemplul de a crea un obiect al unei masini cu diferite tipuri de masini, care sunt Sedan, SUV, etc. Voi continua acelasi exemplu pentru a explica modelul Metoda Factory astfel incat vom avea o mai buna idee și continuitate.

Problema

Într-o fabrică simplă, am creat un obiect al clasei de mașină, dar de fapt a fost crearea unui obiect al clasei de mașină pe baza tipului de mașină pe care l-am trecut. Acesta a fost un pas bun pentru a începe cu crearea de obiecte pentru o mașină cu diferite tipuri.

Anterior, compania noastră sa limitat la vânzarea unei mașini numai în SUA și are un singur centru de producție numai în SUA. Dar, pe măsură ce timpul trece, compania se extinde și decide să vândă mașini în Marea Britanie și să construiască un nou centru de producție și în Marea Britanie.

În ambele centre de producție, codul nostru vechi de construcție a mașinilor funcționează bine, dar apoi pentru a îmbunătăți satisfacția clienților, compania decide asupra unor modificări ale modelului de mașină, dar numai pentru mașinile din Regatul Unit. În acest stadiu, codul nostru pentru a construi un obiect al unei mașini va eșua deoarece avem nevoie de câteva caracteristici suplimentare (atribute) pentru un anumit tip de autovehicule.

Avem două opțiuni în acest caz: fie să modificăm codul curent (mai multe condiții altfel) pentru a obține obiectul dorit de mașină, fie pentru a restructura clasele noastre într-un mod care să nu necesite condiții murdare dacă altfel în clasă și în viitor doriți să adăugați mai multe funcții, dar numai pentru anumite categorii limitate.

Prima abordare cu care nimeni nu ar vrea să meargă, deoarece este un fel de mozaic pe care-l faci în codul tău și nu în implementarea reală. În următoarea secțiune, vom vedea cum putem implementa a doua abordare utilizând modelul de proiectare a metodei Factory.

Soluția

Acest model de design se încadrează în categoria modelului structural, deci este mai preocupat de modul în care vă structurați clasele. Deci haideți să ajungem la soluția problemei noastre prin structurarea clasei noastre în mod corespunzător.

Într-o fabrică simplă, nu am folosit o structură pentru că aveam nevoie doar de o clasă care să fie responsabilă pentru crearea unui obiect al mașinii. Pe baza problemei curente, trebuie să creați o clasă separată de fabrică pentru ambele centre de producție, așa că dorim să ne asigurăm că toate fabricile noastre urmăresc același proces pentru a crea un obiect al unei clase. Prin urmare, vom realiza o interfață pe care atât fabrica din SUA, cât și cea din Marea Britanie o va implementa.

interfața carFactory funcția publică buildCar ($ type); 

Acum, interfața noastră pentru fabrici este gata și este timpul să creăm clase ale fabricilor noastre, care sunt fabricile de mașini din SUA și Marea Britanie.

// Clasa fabrică pentru a construi USCarFactory bazată pe clasa US implementează carFactory funcția publică __construct ()  funcția publică buildCar ($ type) $ car = null; comutator (tip $) caz 'suv': $ car = new USSuvFactory (); pauză; caz "sedan": $ car = nou USSedanFactory (); pauză; implicit: $ car = nou USSedanFactory (); pauză;  retur $ mașină;  // Clasa de fabrică pentru a construi UKCarFactory bazată pe Marea Britanie implementează carFactory funcția publică __construct ()  funcția publică buildCar ($ type) $ car = null; comutator (tip $) caz 'suv': $ car = new UKSuvFactory (); pauză; cazul sedan: $ car = new UKSedanFactory (); pauză; implicit: $ car = new UKSedanFactory (); pauză;  retur $ mașină; 

În această etapă, pregătim clasele noastre de fabrică și este momentul să creăm clasa noastră de beton. Dar, la fel ca în fabrică, dorim ca clasele noastre concrete să pună în aplicare anumite metode necesare care sunt comune tuturor claselor concrete.

mașină de interfață function public getLocation (); funcția publică getType (); 

Am adăugat foarte multe metode de bază la clasa noastră pentru a obține locația și tipul de mașină. Acum vom implementa clasele noastre concrete ca mai jos.

clasa USSuvFactory implementează mașina privat $ location; private $ carType; funcția publică __construct () $ this-> location = 'US'; $ this-> carType = 'SUV';  funcția publică getLocation () return $ this-> location;  funcția publică getType () return $ this-> carType;  clasa USSedanFactory implementează mașina private $ location; private $ carType; funcția publică __construct () $ this-> location = 'US'; $ this-> carType = 'Sedan';  funcția publică getLocation () return $ this-> location;  funcția publică getType () return $ this-> carType;  clasa UKSuvFactory implementează mașina privat $ location; private $ carType; funcția publică __construct () $ this-> location = 'UK'; $ this-> carType = 'SUV';  funcția publică getLocation () return $ this-> location;  funcția publică getType () return $ this-> carType;  clasa UKSedanFactory implementează mașina privat $ location; private $ carType; funcția publică __construct () $ this-> location = 'UK'; $ this-> carType = 'Sedan';  funcția publică getLocation () return $ this-> location;  funcția publică getType () return $ this-> carType; 

Am terminat cu punerea în aplicare a claselor noastre concrete, care de fapt sunt un obiect de mașină bazat pe locația și tipul de mașină. Ceea ce a mai rămas este să utilizați această implementare pentru a vedea cum rezolvă problema noastră explicată mai sus.

// US Car Factory $ USFactory = noul USCarFactory (); // Model SUV bazat pe SUA $ USSuv = $ USFactory-> buildCar ('suv'); echo $ USSuv-> getLocation (). ' bazat '. $ USSuv-> gettype (); // Model sedan din SUA $ USSedan = $ USFactory-> buildCar ('sedan'); echo $ USSedan-> getLocation (). ' bazat '. $ USSedan-> gettype (); // UK Car Factory $ UKFactory = noul UKCarFactory (); // Model SUV din Marea Britanie $ UKSuv = $ UKFactory-> buildCar ('suv'); echo $ UKSuv-> getLocation (). ' bazat '. $ UKSuv-> gettype (); // Modelul britanic bazat pe sedan $ UKSedan = $ UKFactory-> buildCar ('sedan'); echo $ UKSedan-> getLocation (). ' bazat '. $ UKSedan-> gettype ();

Puteți spune că am creat în mod eficient obiecte din toate tipurile posibile de mașini cu locația. Clasele noastre sunt bine structurate acum, astfel încât nu va fi prea multă problemă să adăugați o nouă fabrică.  

Adăugarea unei noi clase de fabrică

Să ne imaginăm că o companie a decis să înceapă un nou centru de producție în Australia.

Pe măsură ce clasele noastre sunt bine structurate acum, nu va fi o problemă care să adauge o nouă clasă acum pentru a construi un obiect de mașină pentru centrul de producție australian. 

// Clasa fabrică pentru a construi AUSCarFactory bazată pe clasa AUS implementează carFactory funcția publică __construct ()  funcția publică buildCar ($ type) $ car = null; comutator (tip $) caz 'suv': $ car = nou AUSSuvFactory (); pauză; cazul "sedan": $ car = nou AUSSedanFactory (); pauză; implicit: $ car = nou AUSSedanFactory (); pauză;  retur $ mașină;  // Clase de beton pentru clasa AUS bazată pe AUSSuvFactory implementează mașina privat $ location; private $ carType; funcția publică __construct () $ this-> location = 'AUS'; $ this-> carType = 'SUV';  funcția publică getLocation () return $ this-> location;  funcția publică getType () return $ this-> carType;  clasa AUSSedanFactory implementează mașina private $ location; private $ carType; funcția publică __construct () $ this-> location = 'AUS'; $ this-> carType = 'Sedan';  funcția publică getLocation () return $ this-> location;  funcția publică getType () return $ this-> carType;  // AUS Car Factory $ AUSFactory = nou AUSCarFactory (); // Model SUV bazat pe AUS $ AUSSuv = $ AUSFactory-> buildCar ('suv'); echo $ AUSSuv-> getLocation (). ' bazat '. $ AUSSuv-> gettype (); // Model bazat pe AUS Sedan $ AUSSedan = $ AUSFactory-> buildCar ('sedan'); echo $ AUSSedan-> getLocation (). ' bazat '. $ AUSSedan-> gettype ();

Înfășurarea în sus

Așadar, am văzut cum putem structura clasele noastre astfel încât acestea să poată fi extinse fără a face schimbări în clasele de bază și în codul clientului. Simțiți-vă liber să adăugați contribuțiile dvs. în secțiunea de comentarii de mai jos sau să vă trimiteți un tweet la @XpertDevelopers.

Cod