Patró de disseny Factory

7 min de lectura

Quan programem en un llenguatge orientat a objectes sempre hem de crear objectes de classes que vam crear i fins i tot de classes ja existents.

El problema ve quan tenim objectes que tenen informació similar, però són dividits en classes diferents, és a dir, que cada objecte s’identifiqui per les seves diferències. Moltes confusions s’aconsegueixen quan es vol instanciar d’una certa classe, però això es pot evitar utilitzant un patró de disseny.

Bàsicament els patrons de disseny són solucions a problemes senzills de el desenvolupament de programari. Hi ha patrons de disseny que s’enfoquen en diferents tasques, però el que veurem aquí és un patró creacional.

Els patrons creacionals ajuden a generar una forma flexible de crear objectes sense haver de recórrer a fer servir l’operador new i l’ús de l’constructor original de la classe.

patró de disseny “Factory”

el patró de disseny “Factory” s’enfoca en la creació d’una interfície que faciliti la creació d’objectes que s’organitzen per diferents subclasses. Això passa sovint quan es fa ús de l’herència. Una classe abstracta es genera contenint els atributs generals, i després es creen classes per a objectes específics. Per evitar cridar constructors específics s’han de crear interfícies que ens ajudin en aquestes tasques.

En aquest patró de disseny hi ha dues formes de generar les interfícies per crear objectes: El mètode Factory (Factory method) i el “Abstract Factory “.

mètode Factory (Factory Method)

El mètode Factory és bastant senzill d’explicar i implementar. Es tracta d’un simple mètode agregat dins d’una classe que, per mitjà de un paràmetre o diversos paràmetres, es decideix quin tipus d’objecte crear per llavors retornar i poder utilitzar-lo. Això fa que no tinguem d’importar nombroses classes i molt menys instanciar molts objectes d’aquestes mateixes classes.

Aquí es mostra un exemple elaborat en Javascript de com es fa servir el mètode Factory. Cal tenir en compte que en Javascript no existeixen les classes ni l’herència, de manera que tot es fa en base a funcions.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

// El nostre “Fact ORY Method “
// S’enfoca en l’elaboració d’objectes que comparteixen la mateixa descripció
// però que es divideixen en subclasses per a distingir-
// tots fan servir massa original i el mateix tipus de salsa, però els ingredients
// són diferents.
function Fabrica () {
this.crearPizza = function (tipus) {
// El nostre objecte genèric
var pizza;
// Aquí es decideix l’objecte de la subclasse que es crearà usant aquest mètode
switch (tipus) {
casi ‘original’:
pizza = new Original ();
break;
casi ‘especial’:
pizza = new Especial ();
break;
casi ‘vegetarià’:
pizza = new Vegetarià ();
break;
}
// Atributs generals de totes les pizzes
// Totes les pizzes comparteixen aquesta mateixa informació
// L’única diferència són els ingredients
pizza.tipo = tipus;
pizza.masa = ‘original’;
pizza.salsa = ‘tomàquet’;
pizza.queso = ‘mozzarela’;
return pizza;
}
}
var Original = function () {
this.ingredientes = ‘peperoni’;
};
var Especial = function () {
this.ingredientes = ‘peperoni, cansalada, salsitxa italiana’;
};
var Vegetarià = function () {
this.ingredients = ‘ceba, pebrot’;
};
// Iniciem un array per emmagatzemar diverses pizzes
var pizzes =;
// Creem un objecte de la fàbrica per a generar les pizzes
var fabriqueta = new Fabrica ();
// Una variable temporal per a guardar les cadenes temporals amb la informació de l’objecte
var temp = ”;
// CREACIÓ DE LES PIZZES
pizzas.push (fabriquita.crearPizza ( ‘especial’));
pizzas.push (fabriquita.crearPizza ( ‘vegetarià’));
pizzas.push (fabriquita.crearPizza ( ‘original’));
pizzas.push (fabriquita.crearPizza ( ‘especial’));
pizzas.push (fabriquita.crearPizza ( ‘original’));
// Un bucle FOR per imprimir en alerts la informació de cada objecte
for (var i = 0; i < pizzes. length; i ++) {
temp = (i + 1) + ‘.- \ nTipo:’ + pizzas.tipo + ‘\ nIngredientes:’ + pizzas.ingredientes + ‘\ nMasa:’ + pizzes. massa + ‘\ nSalsa:’ + pizzas.salsa + ‘\ nQueso:’ + pizzas.queso;
alert (temp);
temp = ”;
}

Aquí pots provar el codi en execució: LINK DE PROVA FACTORY METHOD

Aquí pots descarregar el codi: LINK DESCÀRREGA FACTORY METHOD

en aquest exemple es pot apreciar que tenim la funció anomenada Fàbrica, la qual s’enfoca en crear i retornar-un objecte pizza. El paràmetre que rep, anomenat tipus, ajuda a decidir quin tipus de pizza necessitem. Aquí s’utilitza un switch per decidir de quin classe (o en aquest cas, de quin funció) hem de instanciar el nostre objecte. Un cop decidit, s’agreguen els atributs que totes les pizzes tenen en comú, que són la massa, la salsa i el formatge que utilitzen.

Cada funció específica per als tipus de pizza simplement afegeixen l’atribut ingredient i aquest valor canvia depenent de l’tipus instanciat.

a l’hora de crear les pizzes, podem notar que no vam haver de manar a cridar cap operador new ni nomenar cap constructor que definim per a les pizzes. Ara només vam crear un objecte anomenat fabriqueta i aquest se li mana a cridar al seu mètode anomenat crear pizza amb un paràmetre per veure quin objecte s’ha de crear i emmagatzemar en l’arranjament pizzes.

Abstract Factory

a l’contrari el mètode Factory, el Abstract Factory s’enfoca a tenir una fàbrica única per a aquests objectes. Es creen fàbriques en classes separades que s’enfoquen a crear un cert tipus d’objecte i llavors evitar cridar els constructors originals.

En el següent exemple es creen fàbriques d’objectes de tipus llibre i revista. Tots dos contenen el mateix tipus de camp, però es tracten com a objectes diferents.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

// Creem la nostra funció que representa el “constructor” de l’objecte llibre
// Rep de paràmetre un valor que serà el seu nom
function Llibre (nom) {
this.nombre = nom;
}
// Funció que es dedica a crear l’objecte llibre per nosaltres
// Ens estalvia escriure l’operador “new” per crear llibres
function fabricaLibro () {
this.crear = function (nom) {
return new Llibre (nom);
};
}
// Creem la nostra funció que representa el “constructor” de l’objecte revista
// Rep de paràmetre un valor que serà el seu nom
function Revista (nom) {
this.nombre = nom;
}
// Funció que es dedica a crear l’objecte revista per nosaltres
// Ens estalvia escriure l’operador “new” per crear revistes
function fabricaRevista () {
this.crear = function (nom) {
return new Revista (nom);
};
}
// Creem un array que ens guarda els llibres i revistes
var biblioteca =;
// Tenim un objecte de la fàbrica de llibres
var fabriquitaLibro = new fabricaLibro ();
// Tenim un objecte de la fàbrica de revistes
var fabriquitaRevista = new fabricaRevista ();
// Tenim una variable temporal que ens serveix per guardar la informació dels objectes per imprimir
var temp = ”;
// CREACIÓ DE LES PUBLICACIONS
biblioteca.push (fabriquitaLibro.crear ( ‘Harry Potter’));
biblioteca.push (fabriquitaLibro.crear ( ‘Lluna de plutó’));
biblioteca.push (fabriquitaRevista.crear ( ‘MAD’));
biblioteca.push (fabriquitaRevista.crear ( ‘Molt interessant’));
// bucle for que ens serveix per guardar els noms dels articles dins d’una variable
for (var i = 0; i < biblioteca.length; i ++) {
temp + = i + ‘.-‘ + biblioteca.nombre + ‘\ n’;
}
// Imprimim tota la informació en un alert
alert (temp);

Aquí pots provar el codi en execució: LINK DE PROVA ABSTRACT FACTORY

Aquí pots descarregar el codi: LINK DESCÀRREGA ABSTRACT FACTORY

el codi mostra funcions enfocades a la creació individual de llibres i revistes, a l’igual que fàbriques per crear aquests objectes. Aquest patró de disseny ajuda a deixar més clar el quin tipus d’objecte estem creant, però sense accedir als constructors originals. Tot el treball que porta el construir l’objecte es delega a aquestes funcions de fàbrica.

Conclusió

Els patrons de disseny són tècniques útils per a programes complexos i que necessiten l’ús consecutiu d’herència . A el principi ha de semblar alguna cosa no molt rellevant o necessari, però sens dubte evita aquestes molèsties d’importació, i més quan es treballa amb codis aliens i s’ha d’investigar l’ús adequat de les seves constructors.

Jo el veig com una forma d’organització que hauria de ser implementat per moltes persones. Si això es practica de forma consecutiva, llavors els nostres codis serien summament pràctics, es mantindria l’encapsulament de les nostres classes i ens facilita la portabilitat de codi.

Deixa un comentari

L'adreça electrònica no es publicarà. Els camps necessaris estan marcats amb *