Dalla sua pub­bli­ca­zio­ne nel 1994 sono state vendute più di 500.000 copie di Design Patterns: Elements of Reusable Object-Oriented Software. Questo libro per svi­lup­pa­to­ri software descrive 23 diversi tipi di design pattern, co­no­sciu­ti come i design pattern della Gang of Four; il nome deriva dal gruppo di quattro autori Erich Gamma, John Vlissides, Ralph Johnson e Richard Helm. Tra le numerose strategie di design racchiuse in questa opera si annovera anche il co­sid­det­to factory method (“metodo di fabbrica”), detto anche factory pattern, che permette a una classe di delegare la creazione di oggetti alle sot­to­clas­si.

Che cos’è il factory pattern?

Il factory method pattern descrive un approccio di pro­gram­ma­zio­ne con il quale creare oggetti senza bisogno di dover spe­ci­fi­ca­re la loro classe. Questo permette di cambiare co­mo­da­men­te e in maniera fles­si­bi­le l’oggetto creato. Lo svi­lup­pa­to­re sceglie se spe­ci­fi­ca­re il factory method in un’in­ter­fac­cia e quindi im­ple­men­tar­lo come classe figlio o come classe base ed even­tual­men­te so­vra­scri­ver­lo dalle classi derivate. Questo metodo opera a livello della classe co­strut­to­re standard per separare la co­stru­zio­ne degli oggetti dagli oggetti stessi e per­met­te­re così l’utilizzo dei principi SOLID.

N.B.

I principi SOLID sono una parte dei principi del design orientato agli oggetti, che hanno lo scopo di mi­glio­ra­re i processi di sviluppo dei software orientati agli oggetti. L’acronimo “SOLID” sta per i seguenti cinque principi:

- Single re­spon­si­bi­li­ty principle: ogni classe deve possedere un’unica re­spon­sa­bi­li­tà.

- Open/closed principle: le unità del software devono essere esten­di­bi­li senza mo­di­fi­car­ne il com­por­ta­men­to.

- Liskov sub­sti­tu­tion principle: una classe derivata deve sempre poter essere so­sti­tui­ta dalla sua classe base.

- Interface se­gre­ga­tion principle: le in­ter­fac­ce devono cor­ri­spon­de­re per­fet­ta­men­te alle richieste dei client che ef­fet­tua­no l’accesso.

- Dependency inversion principle: le classi con un livello di astra­zio­ne elevato non devono mai dipendere da classi con un livello di astra­zio­ne più basso.

Si parla quindi di factory method ma anche di factory pattern o factory design pattern, no­no­stan­te queste versioni non vengano mai men­zio­na­te nell’opera della GoF. Oltre al già men­zio­na­to factory method pattern, sfo­glian­do il libro trovate solamente l’abstract factory pattern, utile a definire l’in­ter­fac­cia per la creazione di una famiglia di oggetti le cui classi concrete vengono definite soltanto durante l’ese­cu­zio­ne.

Qual è lo scopo del factory design pattern?

Il factory pattern serve a risolvere un problema di fondo durante l’istan­zia­zio­ne, ossia la creazione di un oggetto concreto di una classe, nell’ambito della pro­gram­ma­zio­ne orientata agli oggetti. Creare un oggetto di­ret­ta­men­te all’interno della classe di cui l’oggetto ha bisogno, è possibile ma molto poco fles­si­bi­le. Infatti, la classe viene collegata all’oggetto preciso, rendendo im­pos­si­bi­le mo­di­fi­ca­re l’istan­zia­zio­ne, in­di­pen­den­te­men­te dalla classe. Un codice di questo tipo può essere evitato grazie al factory pattern che definisce un’ope­ra­zio­ne separata per la creazione dell’oggetto – il co­sid­det­to metodo factory – so­sti­tuen­do la classe co­strut­to­re nella creazione dell’oggetto.

Factory pattern: diagramma UML del modello Factory

Nei software adatti all’impiego del factory design pattern, il codice dell’oggetto da creare (definito in queste cir­co­stan­ze anche come “prodotto”) viene ester­na­liz­za­to se­pa­ra­ta­men­te in una propria classe. Questa classe astratta chiamata anche “creator” o “factory” delega l’istan­zia­zio­ne dell’oggetto a una sot­to­clas­se (Con­cre­te­Crea­tor), la quale decide infine che prodotto creare. A questo scopo il Con­cre­te­Crea­tor adopera il metodo crea­te­Pro­duct() e fornisce in risposta un Con­cre­te­Pro­duct, am­plia­bi­le dal Creator uti­liz­zan­do un codice di creazione, prima che il prodotto finito venga trasmesso all’in­ter­fac­cia.

Il seguente diagramma di classe UML aiuta a chiarire il fun­zio­na­men­to del factory pattern, rias­su­men­do gra­fi­ca­men­te le relazioni e i processi descritti.

Vantaggi e svantaggi del factory design pattern

Con il factory pattern l’ese­cu­zio­ne di un metodo di programma è com­ple­ta­men­te separata dall’im­ple­men­ta­zio­ne di nuove classi, il che porta con sé alcuni vantaggi. Questo ha un effetto par­ti­co­lar­men­te positivo sull’am­plia­bi­li­tà del software: le istanze factory pos­sie­do­no un elevato grado di autonomia e per­met­to­no l’aggiunta di nuove classi durante l’ese­cu­zio­ne senza alterare in alcun modo l’ap­pli­ca­zio­ne. È suf­fi­cien­te im­ple­men­ta­re le in­ter­fac­ce factory e suc­ces­si­va­men­te istan­zia­re il Creator (passando per il Con­cre­te­Crea­tor).

Un ulteriore vantaggio consiste nella buona te­sta­bi­li­tà delle com­po­nen­ti factory. Se, ad esempio, un Creator im­ple­men­ta tre classi, la loro fun­zio­na­li­tà può essere testata sin­go­lar­men­te e in­di­pen­den­te­men­te dalla classe in ese­cu­zio­ne. Per farlo, è suf­fi­cien­te as­si­cu­rar­si che le classi ri­chia­mi­no cor­ret­ta­men­te il Creator, anche nel caso in cui venissero apportate delle modifiche al software in un secondo momento. Al­tret­tan­to van­tag­gio­sa è la pos­si­bi­li­tà di assegnare ai metodi di fabbrica un nome si­gni­fi­ca­ti­vo, pos­si­bi­li­tà non concessa alla classe co­strut­to­re.

Il grande punto debole del factory design pattern è che la sua ap­pli­ca­zio­ne porta a un aumento delle classi coinvolte, in quanto ogni Con­cre­te­Pro­duct richiede sempre anche un Con­cre­te­Crea­tor. L’approccio factory è van­tag­gio­so per la pos­si­bi­li­tà di espan­sio­ne del software, ma presenta degli svantaggi per quanto riguarda l’impegno ne­ces­sa­rio. Se deve essere aggiunta una famiglia di prodotti, non deve essere adeguata solamente l’in­ter­fac­cia, ma anche tutte le classi di Con­cre­te­Crea­tor sot­to­stan­ti. Risulta perciò ir­ri­nun­cia­bi­le una buona pia­ni­fi­ca­zio­ne sulla base del tipo di prodotto de­si­de­ra­to.

Vantaggi Svantaggi
Esten­sio­ne modulare dell’ap­pli­ca­zio­ne Elevato numero di classi richieste
Buona te­sta­bi­li­tà L’am­plia­men­to dell’ap­pli­ca­zio­ne è molto im­pe­gna­ti­vo
Pos­si­bi­li­tà di assegnare nomi si­gni­fi­ca­ti­vi ai metodi  

Dove viene impiegato il factory method pattern?

Il factory pattern trova ap­pli­ca­zio­ne in diversi contesti, in modo par­ti­co­la­re, nei software in cui i prodotti concreti da creare non sono co­no­sciu­ti o ben definiti in pre­ce­den­za, il suo approccio al­ter­na­ti­vo per la gestione delle sot­to­clas­si risulta par­ti­co­lar­men­te van­tag­gio­so. Alcuni esempi classici di utilizzo sono i framework o le librerie di classe, diventate l’ar­chi­tet­tu­ra di base pressoché ir­ri­nun­cia­bi­le per lo sviluppo delle moderne ap­pli­ca­zio­ni.

Anche i sistemi di au­ten­ti­ca­zio­ne godono dei vantaggi offerti dai factory design pattern. Al posto di una classe centrale con diversi parametri che variano a seconda dei permessi utente, con i factory pattern si può delegare il processo di au­ten­ti­ca­zio­ne alle classi factory, capaci di prendere decisioni au­to­no­ma­men­te sulla gestione dei vari utenti.

Inoltre, un design dotato dell’approccio factory pattern è ge­ne­ral­men­te adatto a qualsiasi software nel quale vengono aggiunte re­go­lar­men­te nuove classi secondo pia­ni­fi­ca­zio­ne. So­prat­tut­to se queste classi devono eseguire lo stesso processo di creazione.

Factory pattern: esempio in PHP

Il factory pattern può essere uti­liz­za­to in ap­pli­ca­zio­ni con i linguaggi di pro­gram­ma­zio­ne più diversi. Tra i più comuni si an­no­ve­ra­no Java, Ja­va­Script, C++, C#, Python e PHP. L’ultimo di questi linguaggi di scripting è quello usato nell’esempio riportato qui sotto, per il quale ci siamo ispirati a un articolo tedesco del blog Ph­p­mon­keys.

Lo scenario prevede l’utilizzo di una classe astratta “Car” (Creator) e la classe factory “Car­Fac­to­ry” (Con­cre­te­Crea­tor). La prima è pro­get­ta­ta nella maniera più semplice possibile e contiene solamente il codice utile a de­ter­mi­na­re il colore dell’auto (colore standard: bianco) e a eseguirlo:

class Car {
	private $color = null;
	public function __construct() {
		$this->color = "white";
	}
	public function setColor($color) {
		$this->color = $color;
	}
	public function getColor() {
		return $this->color;
	}
}

Nella classe factory vengono invece in­tro­dot­ti i metodi necessari per au­to­mo­bi­li di colore rosso e blu, così come anche un metodo privato per la creazione delle classi vere e proprie:

class CarFactory {
	private function __construct() {
	}
	public static function getBlueCar() {
		return self::getCar("blue");
	}
	public static function getRedCar() {
		return self::getCar("red");
	}
	private static function getCar($color) {
		$car = new Car();
		$car->setColor($color);
		return $car;
	}
}

Grazie al factory method pattern si può inoltre scegliere di ampliare questa classe factory di facile lettura ag­giun­gen­do le ca­rat­te­ri­sti­che più svariate, come altri colori, il marchio o il prezzo dell’auto.

Vai al menu prin­ci­pa­le