Professional Documents
Culture Documents
patrons
PID_00276105
Cap part d'aquesta publicació, incloent-hi el disseny general i la coberta, no pot ser copiada,
reproduïda, emmagatzemada o transmesa de cap manera ni per cap mitjà, tant si és elèctric com
mecànic, òptic, de gravació, de fotocòpia o per altres mètodes, sense l'autorització prèvia
per escrit del titular dels drets.
© FUOC • PID_00276105 Catàleg de patrons
Índex
Introducció.................................................................................................. 5
Objectius....................................................................................................... 6
1. Taula de referència............................................................................ 7
2. Principis de disseny........................................................................... 9
2.1. Baix acoblament (Low coupling) .................................................. 9
2.2. Alta cohesió (High cohesion) ........................................................ 9
2.3. Obert-tancat (OCP, Open-closed principle) .................................... 10
2.3.1. Llei de Demeter (Law of Demeter) .................................. 10
2.4. No-repetició (DRY, Don't repeat yourself) ..................................... 11
2.5. Substitució de Liskov (LSP, Liskov substitution principle) .............. 11
2.6. Segregació d'interfícies (ISP, Interface-segregation principle) .......... 11
2.7. Inversió de dependències (DIP, Dependency inversion principle) ... 12
3. Patrons d'anàlisi................................................................................. 13
3.1. Associació històrica ..................................................................... 13
3.2. Objecte compost (Composite) ...................................................... 17
3.3. Quantitat (Quantity) .................................................................... 18
3.4. Rang (Range) ................................................................................ 21
4. Patrons d'arquitectura..................................................................... 23
4.1. Arquitectura en capes (Layers) .................................................... 23
4.2. Injecció de dependències (Dependency injection) ......................... 25
4.3. Model, vista i controlador (MVC, Model-view-controller) ............. 28
6. Patrons de disseny............................................................................. 40
6.1. Estat (State) .................................................................................. 40
6.2. Façana (Facade) ............................................................................ 43
6.3. Iterador (Iterator) ......................................................................... 46
6.4. Mètode factoria (Factory method) ................................................ 49
6.5. Mètode plantilla (Template method) ............................................ 51
6.6. Observador (Observer) .................................................................. 53
6.7. Ordre (Command) ........................................................................ 57
© FUOC • PID_00276105 Catàleg de patrons
Exercicis d'autoavaluació........................................................................ 67
Solucionari.................................................................................................. 68
Bibliografia................................................................................................. 70
© FUOC • PID_00276105 5 Catàleg de patrons
Introducció
Per a l'aplicació dels patrons a les diferents etapes del cicle de vida del desen-
volupament, cal disposar d'un catàleg que ens permeti cercar i fer referència
de manera ràpida als diferents patrons.
Aquest mòdul conté un catàleg organitzat segons les etapes del cicle de vida
en què es poden aplicar els diferents patrons (anàlisi, arquitectura, assignació
de responsabilitats i disseny). De cada etapa s'han escollit aquells patrons que
s'han considerat més representatius de la seva categoria i l'ús dels quals és més
generalitzat.
Aquest mòdul també es pot fer servir com a referència durant la realització de
les activitats de l'assignatura.
© FUOC • PID_00276105 6 Catàleg de patrons
Objectius
1. Conèixer una selecció de patrons aplicables a les diferents etapes del cicle
de vida del desenvolupament.
1. Taula de referència
A continuació s'inclou una taula de referència amb un resum de tots els pa-
trons del catàleg. De cada patró se n'indica el nom, el tipus, l'apartat del mò-
dul on s'explica en detall i un resum; també n'indiquem algunes referències
bibliogràfiques.
Adaptador Disseny GOF, LAR, MAR 6.8.1 Permet utilitzar una classe fent servir un conjunt
d'operacions diferents al que oferia originalment.
Arquitectura en capes Arquitectura POSA, LAR 4.1 Organitza un sistema fent que cada element treballi a un
únic nivell d'abstracció.
Associació històrica Anàlisi FOW 3.1 Representa els valors d'una associació al llarg del temps.
Creador Assig. resp. LAR 5.4 Assigna la responsabilitat de crear instàncies a un objecte.
Decorador Disseny GOF, MAR 6.8.2 Afegeix responsabilitats a un objecte sense modificar-ne la
classe.
Estat Disseny GOF, LAR, MAR 6.1 Permet a un objecte variar el seu comportament depenent
del seu estat.
Estratègia Disseny GOF, LAR, MAR 6.8.3 Permet triar entre una família d'algorismes.
Expert Assig. resp. LAR 5.2 Assigna una responsabilitat a l'objecte que té la informació
per a dur-la a terme.
Fabricació pura Assig. resp. LAR 5.3 Crea una nova classe per assignar-li una responsabilitat in-
dependent del domini.
Façana Disseny GOF, LAR, MAR 6.2 Redueix l'acoblament entre subsistemes.
Injecció de dependències Arquitectura FOWDI 4.2 Permet escollir i canviar la implementació dels serveis sen-
se haver de canviar el codi dels clients.
Instància única Disseny GOF, LAR, MAR 6.8.4 Assegura, per a una classe, que només n'hi pot haver una
instància.
Iterador Disseny GOF 6.3 Permet recórrer els elements d'una col·lecció.
Mètode factoria Disseny GOF, LAR 6.4 Crea instàncies d'una classe sense conèixer la subclasse
exacta.
Mètode plantilla Disseny GOF, LAR, MAR 6.5 Implementa diversos algorismes semblants reutilitzant la
part comuna.
MVC Arquitectura POSA 4.3 Organitza les responsabilitats d'interacció amb l'usuari.
Objecte compost Anàlisi GOF, LAR, MAR 3.2 Permet tractar una col·lecció d'objectes i els seus elements
de la mateixa manera.
Objecte nul Disseny MAR 6.8.5 Tracta el valor nul com un objecte.
Observador Disseny GOF, LAR, MAR 6.6 Notifica els canvis en l'estat d'un objecte a altres objectes.
© FUOC • PID_00276105 8 Catàleg de patrons
Ordre Disseny GOF, LAR, MAR 6.7 Tracta una invocació a una operació com un objecte.
Quantitat Anàlisi FOW 3.3 Representa una mesura amb la seva unitat.
Servidor abstracte Disseny MAR 6.8.7 Redueix l'acoblament entre clients i servidors.
© FUOC • PID_00276105 9 Catàleg de patrons
2. Principis de disseny
Per a poder avaluar la qualitat d'un disseny és necessari establir uns certs prin-
cipis que aquest ha de complir. D'aquesta manera, direm que un disseny és de
qualitat en la mesura que s'ajusti a aquests principis de disseny.
Quan una classe té un acoblament alt respecte a altres classes ens trobem amb
el següent:
• És difícil d'entendre.
• És difícil de reutilitzar.
• És difícil de mantenir.
• És fràgil respecte als canvis que es produeixin al sistema.
Una versió més restrictiva d'aquest principi és el conegut com a principi de Bibliografia
la responsabilitat única (SRP, Single-responsibility principle): "Una classe només complementària
Bibliografia
Una entitat de programari (classe, mòdul, funció, etc.) hauria d'estar complementària
Una manera de complir aquest principi és crear abstraccions al voltant dels Principi de Variacions
aspectes que preveiem que han de canviar de manera que es pugui crear una protegides
interfície estable respecte als canvis. Mitjançant aquesta solució, el nostre sis- El nostre disseny ha de mini-
tema estarà obert a l'extensió (afegint noves implementacions de les interfíci- mitzar l'impacte en el sistema
actual dels canvis que es pro-
es definides) però tancat a la modificació (no hem de modificar les interfícies dueixin en el futur i que ja po-
dem anticipar.
definides).
(1)
La llei de Demeter, de vegades resumida com a "No parlis amb desconeguts1", En anglès, "Don't talk to stran-
gers".
és un heurístic que ens ajuda a complir el principi Obert-tancat:
Aquesta llei ens ajuda a reduir l'acoblament respecte a una estructura de clas- Llei de Demeter
ses concreta. A més, potencia l'encapsulació, ja que, per a accedir als objec-
De vegades es fa servir el nom
tes associats a un objecte O, ho haurem de fer per mitjà de les operacions de de Llei de Demeter com a prin-
l'objecte O, de manera que ens assegurem que aquest s'assabentarà de l'accés cipi de disseny en substitució
del principi Obert-tancat.
o manipulació.
Bibliografia
Cada peça de coneixement ha de tenir una única i inambigua represen- complementària
tació en el sistema.
Podeu trobar més informació
sobre el principi de No-repe-
tició a [HUNT].
Aquest principi ens indica que hem d'evitar, sempre que puguem, la duplicació
d'informació i de responsabilitats. Si ho aconseguim, el nostre sistema serà
més senzill i més fàcil de mantenir, ja que, davant d'un canvi o error, podrem
identificar fàcilment quin és el component afectat.
Bibliografia
Les instàncies d'una subclasse C han de ser substituïbles per instàncies complementària
de les superclasses de C.
Podeu trobar més informació
sobre el principi de Substitu-
ció de Liskov a [MAR].
Aquest principi ens indica que una bona jerarquia d'herència ha de respectar
el comportament de les superclasses. Una classe o programa que utilitzés ins-
tàncies d'una superclasse S hauria de poder fer servir qualsevol instància d'una
subclasse de S sense que el seu comportament es vegi afectat negativament.
Bibliografia
Els clients no haurien de dependre d'operacions que no fan servir. complementària
Bibliografia
Els mòduls o classes d'alt nivell no haurien de dependre dels de baix complementària
nivell sinó d'una abstracció.
Podeu trobar més informació
sobre el principi d'Inversió de
Les abstraccions no haurien de dependre dels detalls. Els detalls haurien dependències a [MAR].
de dependre de les abstraccions.
3. Patrons d'anàlisi
Els patrons d'anàlisi són aquells patrons que documenten solucions aplicables Vegeu també
durant la realització del diagrama estàtic d'anàlisi per a resoldre els problemes
Podeu trobar més informació
que hi sorgeixen: ens proporcionen maneres provades de representar concep- sobre els patrons d'anàlisi en
tes generals del món real en un diagrama estàtic de l'anàlisi. l'apartat 2.1 del mòdul "Intro-
ducció als patrons".
Context
Problema
Volem poder recuperar els valors que l'associació ha anat prenent al llarg
del temps.
En concret:
Per exemple, suposem que el sistema que estem desenvolupant necessita em-
magatzemar informació sobre els projectes en què ha participat un empleat,
per la qual cosa ens trobem amb el diagrama estàtic de l'anàlisi següent:
Aquesta solució, però, només ens serveix per a saber, en el moment actual, en
quins projectes participa l'empleat. Com podem saber en quins projectes va
participar l'empleat l'any passat? D'aquesta informació sobre l'estat del sistema
en el passat en diem "informació històrica" i és una situació força habitual en
el desenvolupament de sistemes d'informació.
© FUOC • PID_00276105 14 Catàleg de patrons
Solució
Si els valors que pren l'associació tenen un cert període de validesa, el moment
final d'aquest període s'indicarà com a associació de la classe associativa:
Així, doncs, ara el nostre sistema sap, per a cada parella Empleat-Projecte, la
data en què es va produir aquesta assignació i la data en què l'assignació va
finalitzar. Per a saber quina és l'assignació actual, haurem de mirar quina data
és la més recent o també podríem considerar que és aquella que encara no
tingui dataFi.
A l'hora de definir les noves cardinalitats, cal anar amb compte. En aquest cas,
la cardinalitat al costat d'Empleat ens indicarà quantes instàncies d'Empleat
poden estar associades a un mateix Projecte amb la mateixa Data, però no ens
indica res respecte a altres moments en el temps (per exemple, un Empleat pot
estar assignat més d'una vegada a un Projecte sempre que la data d'assignació
sigui diferent).
Conseqüències
Variacions
Si en lloc d'una associació el que tenim és un atribut del qual volem conèixer
l'historial de valors, cal fer una transformació prèvia: representem l'atribut com
una associació binària entre la classe i el tipus de dades que correspongui i
després apliquem el patró normalment.
Per a aplicar aquest patró, primer ens cal convertir l'atribut en una associació
binària:
• En aquest cas hem suposat que un mateix empleat no pot canviar de sou
més d'una vegada en una mateixa data (restricció que es reflecteix al dia-
grama per la cardinalitat 0..1 al costat Diners). Si no fos així, la cardinalitat
al costat Diners seria *.
Variacions
Context
Problema
Per exemple, suposem que el sistema d'informació que estem desenvolupant Patró d'anàlisi o de
fa servir arxius per a emmagatzemar informació. D'un usuari concret en sabem disseny?
els arxius que li pertanyen, i també el nom i els permisos de cada arxiu. Aquest patró habitualment,
es considera un patró de dis-
seny. L'hem inclòs com a patró
d'anàlisi perquè també pot ser
molt útil en aquesta etapa del
cicle de vida del desenvolupa-
ment de programari.
Ara, però, volem afegir la possibilitat d'agrupar els arxius en carpetes. Sobre
aquestes carpetes volem aplicar el mateix tractament que sobre els arxius (és
a dir, també tindran un nom i uns permisos). Com ho podem fer?
Solució
Conseqüències
• Solució més complexa: hem fet una generalització i, per tant, s'ha afegit
una classe nova.
Context
Problema
Quina solució es pot aplicar en una situació com aquesta que ens permeti
solucionar tots els problemes que hem esmentat abans?
Solució
Podem veure, doncs, que d'aquesta manera podem solucionar els problemes
que hem esmentat abans pel que fa a l'anàlisi i, més endavant, durant l'etapa
del disseny, podrem solucionar el problema de les conversions entre unitats
sense grans dificultats. En el nostre cas, el resultat seria el següent:
© FUOC • PID_00276105 20 Catàleg de patrons
Hem de tenir en compte que, si dues persones fan la mateixa alçada (per exem-
ple, 1,70 cm), cada una tindrà associada una instància diferent d'Alçada amb
els mateixos valors als seus atributs. D'aquesta manera, si es modifica l'alçada
d'una de les dues persones, no es modificarà la de l'altra. És per això que tenim
un 1 a la cardinalitat del costat de Persona.
Conseqüències
• Tenim més classes, la qual cosa provoca que el model guanyi expressivitat
a canvi de perdre simplicitat.
Variacions
• Conversió entre unitats d'una mateixa magnitud (com, per exemple, les
ràtios de conversió de centímetres a polzades).
Aquests altres patrons d'anàlisi, però, ja són molt més específics per a dominis
d'àmbits científics i, especialment, mèdics.
© FUOC • PID_00276105 21 Catàleg de patrons
Context
Problema
El problema d'aquesta solució és que estem afegint a la classe Notícia totes les
responsabilitats associades a la gestió del rang de dates (comparar-les, gestio-
nar-les, etc.). A més a més, si tenim més classes amb rangs de dates, la solució
es complica, ja que el coneixement sobre el funcionament dels intervals de
dates es troba dispers.
Solució
Aquesta classe tindrà un valor d'inici i un valor de final. Considerarem que una Exemple
instància del rang conté tots els valors situats entre el valor d'inici i el valor de
Opcionalment podríem fer ser-
final i que dues instàncies s'encavalquen si contenen algun valor comú. vir una classe parametritzada
per a representar el rang.
Conseqüències
• Només es pot aplicar amb tipus que suportin la comparació (és a dir, que
tinguin definit un ordre per defecte), tot i que es podria fer una versió més
sofisticada en la qual es pogués indicar el criteri d'ordenació.
• Com tractem els rangs oberts (per exemple, més gran que sis)? Podem fer
servir un valor especial (el valor nul, o el màxim representable, etc.) com
a indicador de la manca de límit i encapsular aquest fet dins de la classe
de manera que els clients no es vegin afectats.
Variacions
4. Patrons d'arquitectura
Els patrons d'arquitectura són aquells que s'apliquen en la definició de Vegeu també
l'arquitectura del programari i que, per tant, resolen problemes que afectaran
Podeu trobar més infor-
el conjunt del disseny del sistema. mació sobre els patrons
d'arquitectura en l'apartat 2.2
del mòdul "Introducció als pa-
4.1. Arquitectura en capes (Layers) trons".
Context
Problema
• Es vol dissenyar una arquitectura que eviti que els canvis al codi d'una part
es propaguin per tot el sistema reduint l'acoblament entre parts.
• Es vol evitar que la lògica de negoci i els serveis tècnics de l'aplicació esti-
guin excessivament acoblats per a poder reutilitzar, distribuir o substituir
fàcilment un servei tècnic per una implementació diferent.
Solució
La col·laboració i l'acoblament és des de les capes més altes cap a les més baixes.
Una capa de nivell N només estarà acoblada a la capa de nivell N-1. D'aquesta
manera, cada classe tindrà una visió del sistema més coherent i més senzilla.
• Domini: el seu nivell d'abstracció és el dels conceptes del sistema i les se-
ves responsabilitats les d'implementar les regles de negoci. Les classes de
la capa de domini veuen el sistema com un conjunt de classes d'entitat
(Nòmina, Empleat, etc.) que contenen la informació que gestiona el siste-
ma i una sèrie de casos d'ús o operacions de sistema que en determinen
la funcionalitat.
© FUOC • PID_00276105 25 Catàleg de patrons
En el nostre exemple, per a calcular una nòmina, les diferents capes intervin-
dran de la manera següent:
2) Capa de domini: rebrem una crida a una operació d'una classe que ha de
saber com es fa el càlcul a partir dels seus paràmetres. No ens hem de preocupar
de quins botons s'han polsat ni de quines pantalles es mostren, com tampoc
d'en quins fitxers físics rau la informació que hem de fer servir.
3) Capa de serveis tècnics: la visió que aquestes classes tenen del sistema cons-
ta d'una base de dades, una sèrie de fitxers auxiliars i, potser, un servidor re-
mot al qual enviem dades a través de la xarxa. No saben res de nòmines, ni
empleats, ni interfícies gràfiques d'usuari i només han d'atendre peticions de
lectura/escriptura en disc, consultes a la base de dades, etc.
Conseqüències
Variacions
El nombre i la funció de les capes pot variar d'un sistema a un altre i, de fet,
són dues de les variables a tenir en compte en el moment d'aplicar el patró.
Per exemple, podem fer servir dues capes com als sistemes client/servidor.
Context
© FUOC • PID_00276105 26 Catàleg de patrons
En el nostre sistema tenim definits una sèrie de serveis (com ara l'enviament
de missatges de correu electrònic o un servei de persistència) pels quals tenim
(o podem tenir en un futur) diverses implementacions.
Problema
Solució
Oferir operacions per a poder injectar a les classes usuàries d'un servei
la implementació d'aquest. Aquesta injecció la durà a terme una tercera
classe que, típicament, formarà part d'un bastiment especialitzat.
© FUOC • PID_00276105 27 Catàleg de patrons
Conseqüències
• És més fàcil provar la nostra classe de manera aïllada, ja que no necessitem Bibliografia
modificar el mecanisme de resolució de dependències sinó, simplement, complementària
configurar la instància sobre la qual executarem les proves unitàries amb Podeu trobar més informa-
les implementacions que més ens convinguin per a fer la prova. Per exem- ció sobre proves unitàries
de classes de programari a
ple, per a provar una instància de GestorPersonaBD només li hem de pro- [BECK].
porcionar una implementació de BD cridant l'operació setBD.
• És fàcil identificar cada servei, ja que tots tenen un nom (aquest nom serà
determinat pel nom de l'operació que fem servir per a injectar la imple-
mentació del servei).
Variacions
© FUOC • PID_00276105 28 Catàleg de patrons
• Injecció per constructor: les dependències són paràmetres del constructor Implementacions
del nostre objecte. Això ens assegura que és impossible tenir una instància
Alguns bastiments Java que
que no estigui configurada correctament, ja que es configura en el mateix faciliten l'aplicació d'aquest
moment de la seva creació. Aquesta solució és problemàtica en els llen- patró són PicoContainer
(www.picocontainer.org)
guatges de programació en què els paràmetres no tenen nom si en tenim i Spring Framework
(www.springframework.org).
més d'un del mateix tipus, ja que no tenim manera de diferenciar els dos
serveis.
Context
Problema
Prenem com a exemple un formulari d'edició de les dades d'un usuari que
permet modificar-ne el nom. Un cop canviat el nom, l'usuari ha de polsar el
botó Acceptar.
Solució
(2)
Els models encapsulen l'estat del sistema. El seu nivell d'abstracció és el do- Comportament del sistema en
2 termes del domini.
mini del problema. És on s'implementa l'anomenada lògica de negoci . També
notifiquen a les vistes els canvis en l'estat del sistema.
Les vistes presenten les dades als usuaris i en recullen les interaccions (per
exemple, s'ha polsat un botó d'una pantalla) per enviar-les als controladors.
Demanen l'estat del sistema al model.
Conseqüències
• La cohesió de les classes és més alta perquè totes les seves responsabilitats
estan relacionades.
Els patrons d'assignació de responsabilitats són un tipus especial de patró de Vegeu també
disseny que no s'apliquen per a resoldre un problema concret de disseny sinó
Podeu trobar més informa-
que s'apliquen, de manera general, per a repartir les responsabilitats entre les ció sobre els patrons GRASP a
diferents classes del diagrama de classes. Així doncs, la seva aplicació acostuma [LAR] o a l'apartat 2.3 del mò-
dul "Introducció als patrons".
a ser prèvia a l'aplicació de la resta de patrons de disseny.
Context
Solució
• Controlador de sessió: representa una sessió d'un actor. Una sessió és una
instància d'una conversa entre l'actor i el sistema i pot tenir qualsevol du-
© FUOC • PID_00276105 33 Catàleg de patrons
ració. S'hi poden produir esdeveniments corresponents a tots els casos d'ús
en què l'actor pugui intervenir.
Exemple
Suposem que en un cas d'ús de compra de productes d'una botiga virtual tenim
una petició de consulta d'una categoria de productes:
Però quin objecte de la capa de domini serà l'encarregat d'atendre aquesta pe-
tició? Segons el patró Controlador, ho farà un objecte controlador que podem
definir a diferents nivells:
• Controlador de façana:
• Controlador de sessió:
• Controlador transacció:
estendre fàcilment el sistema afegint noves classes per als nous esdeveni-
ments que vulguem afegir.
Les quatre opcions proposades pel patró controlador tenen els seus avantatges
i inconvenients. Cal escollir una modalitat que no generi un nombre gaire
excessiu de controladors massa simples, però que no creï tampoc controladors
massa sobrecarregats i difícils d'entendre i gestionar.
Corol·lari
(3)
Una conclusió important d'aquest patró de disseny és que s'ha d'evitar de to- en anglès, servlet.
tes maneres que la capa de presentació i els seus components (com ara botó,
finestra, text àrea per a aplicacions d'escriptori o miniaplicacions de servidor3
i JSP per a aplicacions web, etc.) siguin responsables de gestionar els esdeveni-
ments del sistema. És a dir, els esdeveniments de sistema haurien de ser gesti-
onats per la capa de domini.
Context
Solució
Context
Solució
© FUOC • PID_00276105 37 Catàleg de patrons
Se'n diu Fabricació pura perquè la nova classe és una fabricació de la imaginació
(no existeix en el món real) i, atès que les seves responsabilitats estan molt
cohesionades, el seu disseny és molt net, o pur.
Context
Solució
Qui serà el responsable de la creació d'un nou grup d'una assignatura? Segons
el patró creador, com que l'assignatura agrega instàncies de grup, serà la res-
ponsable de la creació de les instàncies de grup. Per tant, la solució serà la
següent:
© FUOC • PID_00276105 40 Catàleg de patrons
6. Patrons de disseny
Els patrons de disseny són aquells que s'apliquen per a resoldre problemes Vegeu també
concrets de disseny que no afectaran el conjunt de l'arquitectura del sistema.
Podeu trobar més informació
sobre els patrons de disseny
6.1. Estat (State) l'apartat 2.4 del mòdul "Intro-
ducció als patrons".
Context
Els objectes d'una classe varien el seu comportament depenent del seu
estat.
Problema
modifica l'estat de la connexió (que passa a estar tancada), mentre que, quan
està tancada, cridar l'operació tancar produeix un error. Se'ns acut un possible
disseny que solucionaria el nostre problema:
Aquesta solució, però, no ens és vàlida perquè el llenguatge que farem servir no
suporta la generalització dinàmica (és a dir, no ens permet que una instància
de connexió canviï de subclasse durant l'execució del sistema), de manera que
necessitem una altra manera de resoldre el problema.
Solució
Conseqüències
Variacions
Per a fer que un objecte Context estigui en més d'un estat al mateix temps,
haurem de modificar la cardinalitat de l'associació al costat de l'Estat posant-hi
un asterisc (*). Això ens pot ser útil quan les diferències entre els estats són
© FUOC • PID_00276105 43 Catàleg de patrons
només relatives als atributs i associacions que es poden tenir, però serà pro-
blemàtic si hi ha operacions que estiguin implementades de manera diferent
en dos dels estats simultanis.
Per a fer que un objecte Estat estigui associat a més d'un context, hem de mo-
dificar la cardinalitat de l'associació al costat del context posant-hi un asterisc
(*). En aquest cas, hem de posar en l'objecte Context tots els atributs de tots
els estats, ja que si estiguessin en l'objecte Estat el seu valor seria compartit per
tots els contextos. Aquesta solució és especialment interessant si els objectes
Estat són costosos de crear i/o mantenir en memòria.
Context
Problema
Per exemple, suposem que el sistema que estem desenvolupant té una classe
anomenada PersonaDAO que conté les operacions per a accedir a la base de
dades de persones. Aquesta classe ha d'accedir a les interfícies de programació
de la base de dades, de manera que està acoblada amb totes les classes del
subsistema de bases de dades:
© FUOC • PID_00276105 44 Catàleg de patrons
Aquest acoblament es repetirà per a totes les classes que accedeixin a la base
de dades. Per exemple, si afegim una classe ClientDAO per accedir a les dades
dels clients, també estarà acoblada amb tot el subsistema de base de dades.
Com podem evitar que tantes classes depenguin del subsistema de base de
dades?
Solució
Crear una nova classe Façana que representi tot el subsistema o capa
accedit.
En cas que vulguem oferir un únic punt d'entrada a B, afegirem una Façana
a B que serà l'única classe pública del subsistema (la resta de classes poden
tenir visibilitat de paquet) per tal d'assegurar-nos que no hi ha cap altra via
d'entrada.
Com es pot veure, en el nou disseny les dependències estan més concentrades.
Qualsevol canvi en el subsistema de base de dades afectarà només la classe
FaçanaBD.
Conseqüències
Context
Problema
D'aquesta manera volem evitar l'acoblament de les nostres classes Client cap
a aquesta estructura (fet que ens dificultaria canviar-la per una altra), així com
possibles manipulacions d'aquesta estructura sense el nostre control.
Volem proporcionar diferents estratègies per a accedir als elements (per exem-
ple, amb criteris d'ordenació diferents).
Per exemple, suposem que el sistema que estem desenvolupant té les classes
següents:
(4)
Com que una Empresa ha de mantenir un conjunt de referències als Empleats En anglès, array.
4
que hi treballen, decidim fer servir un vector per a emmagatzemar aquestes
referències:
Volem afegir una operació a Empresa que ens permeti consultar el conjunt dels
empleats de l'empresa. Si retornem el vector directament, estarem exposant
l'estructura interna de la classe Empresa (amb els problemes que això compor-
ta).
Solució
© FUOC • PID_00276105 48 Catàleg de patrons
Crear una classe Iterador que coneixerà l'estructura interna, com s'ha de
recórrer i com s'ha de modificar (per exemple, notificant-ho a la classe)
i que encapsularà aquest coneixement.
Podem associar una instància d'iterador a cada client de manera que sigui
l'iterador qui tingui la responsabilitat de saber quins elements ha mostrat i
quins no a cada client.
• També podem afegir altres operacions (remove, last, etc.) segons les neces-
sitats concretes de cada cas.
posicioActual = -1;
}
public void reset() {
posicioActual = -1;
}
public boolean hasNext() {
return posicioActual + 1 < dades.length;
}
public Empleat next() {
posicioActual++;
return dades[posicioActual];
}
}
Conseqüències
• Podem variar l'estratègia utilitzada per a accedir als elements (per exemple,
modificant el criteri d'ordenació).
Context
Problema
Una classe delega una responsabilitat a una o més classes d'ajuda i volem aïllar
la responsabilitat de decidir quina classe d'ajuda farem servir.
Solució
Definir, a la classe abstracta Creador (la que crea els objectes), un mè-
tode "crear" encarregat de la creació i que anomenarem mètode factoria.
Proporcionar, a cada subclasse de Creador, una implementació del mè-
tode factoria que creï un tipus concret d'objecte.
En el nostre exemple, aplicarem el mètode factoria fent que la decisió del tipus Vegeu també
de missatge a crear sigui de la subclasse. D'aquesta manera, els usuaris que
Vegeu més informació sobre el
treballin amb un notificador de tipus NotificadorEMail rebran els missatges principi de disseny obert-tan-
per correu electrònic i els que facin servir un NotificadorMMS els rebran al seu cat en l'apartat 2.3 d'aquest
mòdul.
telèfon mòbil. A més, si volem afegir nous mecanismes de notificació al nostre
sistema, només hem d'afegir les noves subclasses de Notificador i de Missatge
respectant, així, el principi obert-tancat.
© FUOC • PID_00276105 51 Catàleg de patrons
Context
Problema
Volem que les subclasses només hagin de redefinir la part que els és específica Vegeu també
i evitar haver de reescriure les parts comunes, la qual cosa violaria el principi
Vegeu més informació sobre
de no-repetició. el principi de no-repetició en
l'apartat 2.4 d'aquest mòdul.
Per exemple, suposem que en el sistema que estem desenvolupant tenim una
sèrie de classes que gestionen l'accés a la base de dades:
© FUOC • PID_00276105 52 Catàleg de patrons
3) Executar la consulta.
4) Tractar el resultat.
Solució
Conseqüències
Context
Problema
© FUOC • PID_00276105 54 Catàleg de patrons
Volem que el nostre sistema estigui obert a l'extensió per a permetre que nous Vegeu també
objectes siguin notificats sense haver de modificar la classe de l'objecte en el
Vegeu més informació sobre el
qual es produeix el canvi. principi de disseny obert-tan-
cat en l'apartat 2.3 d'aquest
mòdul.
Per exemple, suposem que estem desenvolupant un sistema de subhastes elec-
tròniques i tenim les classes següents:
Solució
Conseqüències
Variacions
Una altra opció és que el subjecte no enviï cap informació i que sigui
l'observador qui s'encarregui de demanar el nou estat a tots els subjectes que
observi. D'aquest model se'n diu model estirada en contraposició al model em-
penta, que hem vist anteriorment.
© FUOC • PID_00276105 57 Catàleg de patrons
Context
Volem tractar les crides a operacions com a objectes, per exemple, per al se-
güent:
Problema
Per exemple, volem que el sistema que estem desenvolupant permeti a l'usuari
desfer les accions portades a terme en el sistema (per exemple, si ha modificat
unes dades, desfer la modificació). Si poguéssim tractar cada acció de l'usuari
com un objecte, podríem desar una llista de les accions efectuades per a po-
der-les desfer; però el nostre llenguatge no ens permet tractar les crides a ope-
racions com a objectes.
Solució
Conseqüències
• Podem manipular i estendre les ordres com qualsevol altra classe del siste-
ma (per exemple, podem aplicar el patró Mètode plantilla).
Vegeu també
Permet utilitzar una classe fent servir un conjunt d'operacions diferent
al que ofereix originalment. Podeu trobar una explicació
detallada amb exemples sobre
adaptadors en l'apartat 1.6.1
del mòdul "Introducció als pa-
trons".
Per exemple, en el bastiment d'aplicacions gràfiques Swing de Java, el compo-
nent JTable utilitza la interfície TableModel per a obtenir les dades que ha de
visualitzar. Si volem mostrar les dades d'una estructura de dades pròpia, po-
dem escriure un adaptador per a poder oferir al component JTable la interfície
que espera sense haver de modificar la nostra classe.
Vegeu també
Permet afegir responsabilitats a un objecte dinàmicament.
El Decorador està molt rela-
cionat amb el Representant,
que podeu trobar descrit en
El Decorador té la mateixa interfície que l'objecte que decora, implementa l'apartat 6.8.6 d'aquest mòdul.
les responsabilitats addicionals i delega la resta de responsabilitats a l'objecte
decorat:
Vegeu també
Estratègia i Mètode
Permet definir una família d'algorismes i fer-los intercanviables els uns plantilla
amb els altres. D'aquesta manera, permet escollir-ne un dinàmicament.
El patró de disseny Estratègia
ens permet solucionar proble-
mes molt similars als proble-
mes que soluciona el patró
L'Estratègia permet separar un algorisme general dels detalls concrets de cada Mètode plantilla que podeu
possible implementació facilitant, doncs, la reutilització de l'algorisme general trobar en l'apartat 6.5 d'aquest
mòdul. Sovint en podrem fer
de manera independent dels detalls. A més, permet reutilitzar les implemen- servir un o l'altre indistinta-
ment. La principal diferència
tacions dels detalls per a més d'un algorisme general atès que no fa servir he- rau en el fet que el patró Estra-
tègia fa servir delegació en lloc
rència sinó delegació. d'herència.
© FUOC • PID_00276105 61 Catàleg de patrons
Suposem que en el sistema que estem desenvolupant hem d'ordenar una llista
i volem poder escollir quin algorisme d'ordenació fem servir:
Permet assegurar que, d'una determinada classe, només n'hi ha una ins-
tància en tot el sistema.
Suposem que volem que totes les classes que accedeixin a la base de dades en
la nostra aplicació ho facin per mitjà de la mateixa instància, de tal manera
que puguem controlar fàcilment el nombre de connexions establertes contra
la base de dades. Per a aconseguir-ho, hem de dissenyar la classe d'accés a la
base de dades com una classe d'instància única.
Permet tractar el cas del valor nul com si fos una instància vàlida.
int total;
Comanda c = DB.carregaComanda("W2132");
if (c != null) {
total = c.total();
} else {
total = 0;
}
int total;
Comanda c = DB.carregaComanda("W2132");
total = c.total();
Suposem, per exemple, que estem desenvolupant un sistema que gestiona no-
tícies:
Per a millorar el rendiment del sistema, volem evitar que el cos de les notícies
es carregui fins que sigui necessari. Però voldríem fer-ho de manera transparent
per al Noticiari i per a la Notícia que ja tenim dissenyats.
Exemple
(5)
En anglès, cache.
Queda per resoldre el problema de substituir l'objecte original pel seu repre-
sentant, condició necessària perquè l'aplicació del patró sigui realment trans-
parent a la classe Client. La manera de solucionar-ho serà diferent en cada cas
i queda fora de l'àmbit d'aquest patró.
Aquest patró, en la seva estructura, és molt semblant al patró Decorador. La Vegeu també
principal diferència, però, rau en la seva finalitat: un Decorador afegeix res-
Vegeu més informació sobre
ponsabilitats a un objecte modificant-ne el comportament, mentre que un el patró Decorador en l'apartat
Representant en controla l'accés. 6.8.2 d'aquest mòdul didàctic.
Permet desacoblar una classe client respecte d'una classe que fa servir i
que anomenarem servidor.
© FUOC • PID_00276105 65 Catàleg de patrons
Per a fer-ho, introdueix una abstracció que representa l'ús que el client fa del
servidor.
Aquest disseny acobla la classe interruptor respecte a la classe Llum. A més a Vegeu també
més, s'incompleix el principi obert-tancat: Què passa si volem un interruptor
Vegeu més informació sobre el
per a un ventilador? principi de disseny obert-tan-
cat en l'apartat 2.3 d'aquest
mòdul didàctic.
El patró Servidor abstracte ens diu que introduïm una abstracció entre Inter-
ruptor i Llum que representi l'ús que fa l'interruptor de llums, ventiladors i
qualsevol altra classe que es vulgui controlar més endavant.
Cal destacar el detall del nom de la interfície. La interfície amb les operacions
de Llum es diu ControlatPerInterruptor i no Llum. Això és degut al fet que les
operacions de la interfície són les que sap controlar l'Interruptor i no necessà-
riament totes les de Llum. Per això diem que la interfície pertany a Interruptor
i no a Llum. Amb aquest disseny, qualsevol aparell que implementi Contro-
latPerInterruptor podrà ser controlat per una instància d'Interruptor.
Si els objectes que han d'implementar la nova interfície ja existeixen, segura- Vegeu també
ment ens caldrà adaptar-ne la interfície actual a la que introdueix el Servidor
Vegeu més informació del
abstracte. Per a fer-ho, ens podem basar en el patró Adaptador. patró Adaptador en l'apartat
6.8.1 d'aquest mòdul.
© FUOC • PID_00276105 67 Catàleg de patrons
Exercicis d'autoavaluació
El sistema que estem desenvolupant gestiona informació sobre cotització d'accions, ordres
de compra, i també unes pantalles que mostren la cotització de les diverses empreses.
Els usuaris poden programar ordres de compra de manera que quan la cotització de les accions
d'una empresa baixa per sota d'un cert valor límit (indicat en l'ordre), el sistema compri
automàticament el nombre d'accions que s'ha programat en l'ordre i les afegeix al compte
de l'usuari.
Nota
La classe AccioEnCompte és el
resultat de normalitzar la classe
associativa de l'associació "en-
Cartera" entre Compte i Em-
presa.
1. Volem dissenyar una operació que anomenarem executarOrdreCompra que, donada una
ordre de compra, calcula el valor de les accions comprades, verifica el saldo del compte i,
si el saldo és suficient, afegeix la quantitat d'accions comprades a la cartera del compte i
descompta el preu del saldo. Aplica els patrons d'assignació de responsabilitats per assignar
les diverses responsabilitats associades a aquesta funcionalitat.
Solucionari
Verificar si s'ha d'executar l'ordre de Compra: per a fer-ho caldrà consultar el valor de cotit-
zació (és Empresa qui el coneix) i comparar-lo amb el valor límit de l'ordre (és OrdreCompra
qui el coneix). En aquest cas, per cohesió assignarem aquesta responsabilitat a l'Ordre de
compra de tal manera que sigui l'única que conegui com es decideix si una ordre de compra
és executable.
Si l'ordre és executable, caldrà calcular l'import de compra de les accions, verificar el saldo
del compte i, si hi ha prou saldo, afegir el nombre d'accions indicat en l'ordre de compra al
compte de destinació. En aquest cas, l'Ordre és l'expert per a calcular l'import de compra,
mentre que el Compte és qui coneix el saldo i les accions.
L'expert que sap quantes accions d'una determinada empresa té un compte és la classe Ac-
cioEnCompte.
Pot passar, però, que el Compte no tingui prèviament cap Acció de la mateixa empresa i que
calgui, per tant, crear una nova instància d'AccioEnCompte. En aquest cas, segons el patró
Creador, serà el Compte qui s'encarregui de crear aquesta instància, ja que la instància de
Compte conté les seves instàncies d'AccionsEnCompte.
Nota
En cas que aquesta compra es vulgués efectuar com a resultat d'un esdeveniment generat
per l'usuari caldria, a més, una classe controladora que s'encarregués de rebre aquest es-
deveniment i d'invocar l'operació creada de la classe OrdreCompra.
En l'escenari en què la compra s'acaba efectuant (el valor de cotització està per sota del valor
límit i hi ha prou saldo) i en què el compte no tenia cap acció de l'empresa prèviament, el
diagrama de seqüències resultant de l'assignació de responsabilitats feta anteriorment és el
següent:
© FUOC • PID_00276105 69 Catàleg de patrons
2. El patró Observador ens permet notificar els canvis que es produeixen en una empresa a
aquells objectes que hi estiguin interessats (en el nostre cas, pantalles i ordres de compra)
amb un mínim acoblament.
Nota
L'Empresa cridarà l'operació notificar quan el seu atribut cotitzacio sigui modificat.
L'operació actualitzar d'OrdreCompra invocarà l'operació executar ja dissenyada.
Bibliografia
[FOW] Fowler, M. (1997). Analysis Patterns: Reusable Object Models. Massachusetts: Addison
Wesley Professional.
[GOF] Gamma E., Helm R., Johnson R., Vlissides J. (1995). Design Patterns: Elements of
Reusable Object-Oriented Software. Massachusetts: Addison Wesley Professional.
[LAR] Larman, C. (2003). Una introducción al análisis y diseño orientado a objetos y al proceso
unificado UML Y PATRONES. (2a ed.). Madrid: Prentice Hall.
[MAR] Martin, R.C. (2003). Agile Software Development: Principles, Patterns, and Practices.
Upper Saddle River, New Jersey: Prentice Hall.
Bibliografia addicional
[BECK] Beck, K. (2002). Test Driven Development: By example. Massachusetts: Addison Wes-
ley Professional.
[HUNT] Hunt, A.; Thomas, D. (2000). The Pragmatic Programmer. Massachusetts: Addison
Wesley.
[MEY] Meyer, B. (1999). Construcción de software orientado a objetos. (2a. ed.). Madrid: Pren-
tice Hall.
[POSA] Buschmann, F.; Meunier, R.; Rohnert, H.; Sommerlad, P.; Stal, M. (1996).
Pattern-Oriented Software Architecture: A System Of Patterns. West Sussex, Anglaterra: John Wi-
ley & Sons Ltd.