Sei sulla pagina 1di 6

ma de una imagen depende de las caractersticas de un dispositivo de visualizacin, concretamente de

su capacidad de color y de su resolucin. Sin la.ayuda de los tendran que de-


tenninar qu implementacin usar bajo varias c1rcunstanc1as en cada aphcac!n.
Para aliviar a los desarrolladores de esta responsabilidad, AppKit proporc1ona un puente NXI-
mage/NXImageRep. NXlmage define la interfaz para manipular La implementacin de las
imgenes se define,en una jerarqua de clases separaJa NXJmageRep que subclases NXEP-
SlmageRep, NXCachedl mageRep y NXBitMaplmageRep. t?'l mage una referenc1a a u?o o
ms objetos NXJ mageRep. Si hay ms de una implementacin de una NXlmage
la ms apropfada para el dispositivo de visualizacin actual. NXlmage es capaz convertir
una implementacin en otra si es necesario. El aspecto interesante de esta Bndge es que
NXImage puede almacenar ms de una implementacin de NXJmageRep al m1smo tiempo.
PATRONES RELACIONADOS
El patrn Abstracl Factory (79) puede crear y configurar un Bridge.
El patrn Adapter ( 131) est orientado a conseguir que trabajen juntas clases no estn rela-
cionadas. Nonnalmente se aplica a sistemas que ya han sido diseados. El Bndge, otro la-
do, se usa al comenzar un diseo para pennitir que abstrncciones e implementaciones varen Indepen-
dientemente unas de otras.
)
,.
/



'
-

. .....

... . ...
.....
. . :::: .
..
COMPOSITE
(COMPUESTO)
PROPSITO
Estructural de Objetos
C?mpone objetos en estructuras de rbol para representar jerarquas de parte-todo. Permite que los
clientes traten de manera unifonne a los objetos individuales y a los compuestos.
MOnVACIN
Las aplicaciones grficas como los editores de dibujo y los sistemas de diseo de circuitos penniten a
los usuarios construir diagramas complejos a partir de componentes simples. El usuario puede agru-
par componentes para fonnar componentes ms grandes, que a su vez pueden agruparse para fonnac
componentes a_n mayores. Una implementacin simple podra definir clases para primitivas grficas
como Texto y Lmea, ms otras clases que acten como contenedoras de estas primitivas.
Pero hay un problema con este enfoque: el cdigo que usa estas clases debe tratar de fonna dife-
rente a los objetos primitivos y a los contenedores, incluso aunque la mayor parte del tiempo el usua-
rio los trate de forma idntica. Tener que distinguir entre estos objetos hace que la aplica.:in sea mis
compleja. El patrn Compositt: describe cmo usar.ta composicin recursiva para que los clientes no
tengan que hacer esta distincin.
La clave del p:llrn_Cnmposite es una clase abstrncta que representa tanto a como a sus
contenedores. Para el s1stema grfico, esta clase es Grafico. Grafico declara operaciones como Dibu-
jar que son especficas de objetos grficos. Tambin declara operaciones que comparten todos los ob-
jetos compuestos, tales como operaciones para acceder a sus hijos y para gestionarlos.
Las subclases Linea, Rectangulo y Texto (vlase el diagrama de clases siguiente) definen objetos
grficos primitivos. Estas clases implementan Dibujar para dibujar trneas, rectngulos y texto, respec-
tivamente. Como los grficos primitivos no tienen grficos hijos, ninguna de estas claSes implementa
operaciones relacionadas con los hijos.
--
1 1
Linea Rectangulo
Dibujar() Dibujar()
Gral/ca
Dibujar()
Anadir(Grafico)
Eliminar(Grafico)
ObtenorHlfo(int)
1 T
Texto Dibujo
Dibujar() Dibujar()
Madir(Gralico g) o-
Eliminar(Gratlco)
ObtenerHijo(int)
gratlcos
......... ..... .. ...
-----,
.
.
.
- - - - para todo g en grafteos
g.Dibujar()
,52 Patrones de Diseo
1
La clase Dibujo define una agregacin de objetos Grafico. Dibujo implementa Dibujar para que
llame al Dibujar de sus hijos, y aftade operaciones relacionadas con los hijos. Como la interfaz de Di-
bujo se ajusta a la interfaz de Grafico, los objetos Dibujo pueden componer recursivamente otros
Dibujos.
El siguiente diagrama muestra una tfpica estructura de objetos compuestos recursivamente por
otros objetos Grafio compuestos:

. ; .. J

1
Use el patrn Corilposite cuando
. . : .. .
quiera representar jerarqufas de objetos parte-todo.
quiera que tos clientes sean capaces de obviar las diferencias entre composiciones de objetos y
los objetos individuales. Los clientes tratarn a todos los objetos de la estructura compuesta de
manera uniforme.
ESTRUCTURA
. 1
r
Cliente
1
Componente
r
Operacion()
Anadir(Componente)
Eliminar(Componen/o)
ObtenerHijo(int)
A
r 1
Hoja Compuesto
Operacion() Operacion() o- - - - - -
Anadir(COmponente)
Eliminar(Componente)
ObtenerHijo(int)
hijos

--- -----
para todo g en hijos
g.Operacion();
... :-r
Patrones Estructurales 153
Una estructura de objetos Compuestos tfpica puede parecerse a esto:
PARTICIPANTES
Componente (Grafico)
- declara la interfaz de los objetos de la composicin.
- implementa el comportamiento predeterminado de la interfaz que es comlln a todas las clases .
- declara una interfaz para acceder a sus componentes hijos y gestionarlos.
- (opcional) define una interfaz para acceder al padre de un componente en la estructura recur-
siva y, si es necesario, la implementa.
Hoja (Rectangulo, Linea, Texto, etc.)
- reptsenta objetos hoja en la composicin. Una hoja no tiene hijos.
- define el comportamiento de los objetos primitivos de la composicin.
Compuesto (Dibujo)
- define el comportamiento de los componentes que tienen hijos.
- almacena componentes hijos.
- implementa las operaciones de la interfaz Componente relacionadas con tos hijos.
CUente
- manipula objetos en la composicin a travs de la interfaz Componente.
COLABORACIONES
Los Clientes usan la interfaz de la clase Componente para interactuar con tos objetos de ta estructura
compuesta. Si el recipiente es una Hoja, la peticin se trata correctamente. Si es un Compuesto, nor-
malmente redirige las peticiones a sus componentes hijos, posiblemente realizando operaciones adi-
cionales antes o despus.
CONSECUENCIAS
El patrn Composite
define jerarqufas de clases formadas por objetos primitivos y compuestos. Los objetos primiti-
vos pueden componerse en otros objetos ms complejos, que a su vez pueden ser compuestos, y
asf de manera recurrente. All donde el cdigo espere un objeto primitivo, tambin podr recibir
un objeto compuesto.
simplifica el cliente. Los clientes pueden tratar unifonnemente a las estructuras compuestas y a
los objetos individuales. Los clientes normalmente no conocen (y no les deberfa importar) si es-
tn tratando con una hoj:1 o con un componente compuesto. Esto simplifica el cdigo del clien-
te, puesto que evita tener que escribir funciones con instrucciones 1 f anidadas en las clases que
definen la composicin.
facilita aliad ir nuevos tipos de componentes. Si se definen nuevas subclases Compuesto u Hoja.
tstas funcionarn automticamente con las y el cdigo cliente existentes. No hay que
cambiar los clientes para las nuevas clases COmponente.
puede hacer que un diseilo sea demasiado general. La desventaja de facilitar aliad ir nuevos com-
ponentes es que hace m.s diffcil restringir los componentes de un compuesto. A veces queremos
que un compuesto slo tenga ciertos componentes. Con el patrn Composite, no podemos con-
fiar en el sistema de tipos para que haga cumplir estas restricciones por nosotros. En vez de eso,
tendremos que usar comprobaciones en tiempo de ejecucin.
IMPLEMENTACIN
Hay muchas cuestiones a tener en cuenta al implementar el patrn Composite:
l. Refertncias explfciras al padre. Mantener referencias de los componentes hijos a sus padres
puede simplificar el recorrido y la gestin de una e.strucrura referencia al
facilita ascend9 por la estructura y borrar un componente. Las referenc1as al padre tamb1n
ayudan a implementar el patrn Chain of Responsibility (205).
El lugar habitual donde definir la referencia al padre es en la clase Componente. Las clases
Hoja y Co'mpuesto pueden heredar la referencia y las operaciones que In gestionan.
Con referencias al padre, es esencial mantener el invariante de que todos los hijos de un com-
puesto tienen como padre al compuesto que a su vez los tiene a ellos como hijos. El modo ms
fcil de garantizar esto es cambiar el padre de un componente slo cuilndo se ailade o se eli -
mina a 4!ste de un compuesto. Si se puede implementar una vez en las operaciones Anadir y
Eliminar de J; clase Compuesto entonces puede ser heredado por todas las subclases, conser-
vando automticamente el invariante.
2. Compartir componentes. Muchils veces es til comp:u-lir componentes, por ejemplo para re-
duci(los requisitos de alCllilcenamiento. Pero cuando un componente no puede tener m.s de
un padre, compartir componentes se hace ms diffcil.
Una posible solucin es que los hijos :dmacenen mltiples padres. Pero eso puede llevarnos a
ambigedades cuando Se propaga una peticin hacia arriba en la estructura. El patrn
Flyweight (179) muestra cmo adaptar un diseno para evitar guardar los padres. Funciona en
casos en los que los hijos pueden evitar enviar peticiones al padre extemalizando parte de su
estado, o todo.
3. MaximiuJr la interfat Componente. Uno de los objetivos del patrn Composite es hacer que
los clientes se despreocupen de las clases Hoja o Compuesto que estn usando. Para conse-
guirlo, la clase Componente deberla definir tantas operaciones comunes a las clases Com-
puesto y Hoja como sea posible. La clase Componente nonnalmente proporciona implemen-
taciones predetenninadas para estas operaciones, que sern redefinidas por las subclases Hoja
y Compuesto.
No obstante, este objetivo a veces entra en conflicto con el principio de disei'lo de jerarqufas
de clases que dice que una clase slo debera definir operaciones que tienen sentido en sus
subclases. Hay muchas operaciones pennitidas por Componente que no parecen tener sentido
en las clases Hoja. Cmo puede Componente proporcionar una implementacin predetermi-
nada para ellas?
.. i.
A veces un poco de creatividad muestra cmo un; operacin que podra parecer que slo tie-
ne en el caso de los Compuestos puede implementarse para todos los COmponentes,
mov1ndola a la clase Componente. Por ejemplo, la inteaz para acceder a los hijos es una par-
te fundamental de la clase Compuesto, pero no de las clases Hoja. Pero si vemos a una Hoja
como un Componente que nunca tiene hijos, podemos definir una opercin predeterminada
en la clase Componente para acceder a los hijos que nunca devuelve ningn hijo. Las clases
Hoja pueden usar esa implementacin predeterminada. pero Js clases Compuesto la reimplc-
mentarn p01ra que devuelva sus hijos.
Las operaciones de gestin de los hijos son ms problemticas, y se trotan en el siguiente punto.
4. Declarar las operaciones de gest6n dt los hijos. Aunque la clase Compuesto implemellla las
operaciones A nadir y Elinnar para controlar los hijos, un aspecto imponante del patrn Com-
puesto es qu4! clases declaran estas operaciones en la jerorqufa de clases Compuesto. Debera-
mos declarar estas operaciones en el Componente y hacer que tuvieran sentido en las clases
Hoja, o deberamos declararlas y definirlas slo en Compuesto y sus subclases?
La decisin implica un equilibrio entre seguridad y transparencia:
la interfaz de gestin de los hijos en la rafz de la jerarqufa de clases nos da transpa-
rencia, puesto que podemos tratar 01 todos los componentes de manera uniforme. Sin em-
bargo, sacrifica la seguridad, ya que los clientes pueden intentar hacer cosas sin sentido, co-
mo ailadir y eliminar objetos de las hojas.
Definir In gestin de los hijos en la clase Compuesto nos proporciona seguridad, ya que cual-
quier intento de ailadir o eliminar objetos de l01s hojas ser detectado en tiempo de compilu-
cin en un lenguaje estticamente tipado, como C++. Pero transparencia, porque
las hojas y los compuestos tienen interfaces diferentes.
En este patrn hemos dado ms importancia a la trnnsparencia que a la seguridad. Si se opta
por la seguridad, habr ocasiones en las que perderemos informacin sobre el tipo y tendre-
mos que convertir un componente en un compuesto. Cmo podemos hacerlo sin recurrir a
una conversin que no Sl:a segura con respecto al tipo?
Una posibilidad es declar;u- una operacin COilpuesto ObtenarCompuasto() en la clase Compo-
nente. El Componente proporciona un.1 operacin por omisin que devuelve un puntero nulo. La
clase Compuesto redefine esta operacin para devolverse a sf misma a travis de su puntero this:
class Co11puesto
class C0111ponanta
public:
1/ ..
virtual Compuesto Obtenar Compuesto() ( r eturn e }
} ;
class Compuesto : public Componente
public:
} i
void Anadir(Componenta')
11 ...
- virtual Compuesto ObtenerCompuesto() { return this; }
class Hoja public Componente
11 .
} ;
; Patrones do Diseo
nos permite consultar a un componente para ver si es un compuesto. Po-
demos ejecutar Anadir y EU111lnar con seguridad sobre el compuesto que devuelve.
uncoapuesto new
Ho ja unaHoja new Hoja
,
Componente
prueba;
unC0111ponente unCompuesto;
if (prueba unComponente >ObtenerCompuesto())
Hoja);
unComponente
11 (prueba unComponente>ObtenerCompuesto())
prueba>Anadir(new Hoja): // no a una hoja
Se pueden hacer c9mprobaciones similares para un Compuesto usando la consttuccin de C++
dynamic_cast. )
Por supuesto, (:Vproblema aqul es que no trotamos a todos los componentes de mnnera uni-
forme. TenemOs que volver a realizar comprobaciones para diferentes tipos antes de empren-
der la acci, apropinda.
La nica forma de proporcionar 1ransparencia es definir operaciones predeterminadas Anadlr
i Eliminar en Componente. Eso crea un nuevo problema: no hay modo de implementar Com
ponente: :Anadir sin in1roducir asl mismo la posibilidad de que falte. Podramos no hacer na-
da. pero eso omite una consideracin importante; es decir, un intento de aiiadir algo a una ho-
ja probablemente indicando un error. En ese caso, la operncin Anadir produce basura.
PodamQS hacer que borrara su argumento, pero eso. no es lo que los clientes espe!llll.
Normalmente es mejor hacer que Anadir y Eluinar fallen de manera predeterminada (tal
vez !:miando una si el componente no puede tener hijos o si el argumento de Eli
inar no es un hijo del componente.
Otro posibilidad es cambiar ligeramente el significado de "eliminar". Si el componente man-
tiene unn referencia al padre podamos redefinir Co111ponente: :El1 1nar para eliminarse n se
mismo de su padre. No obstante, sigue sin haber unn interpretacin con sentido para Anadir.
S. Debeda implementar el Componente una lista de Componentes? Podamos estar tentados
de definir el conjunto de hijos como una variable de instancia de la clase Componente en la
que se dectnie las operaciones de acceso y gestin-de tos hijos. Pero poner el puntero al hi
jo en In clase base incurre en un11 penalizacin de espacio para cada hoja, incluso aunque una
hoja nunca tenga hijos. Esto slo merece la pena si hay relativamente pocos hijos en la es
ttuctura.
6. Ordenacin de los hijos. Muchos diseilos especifican una ordenacin de los hijos de: Com
puesto. En el ejemplo del Grafico, la ordenacin puede reflejar el orden desde el frente hasta
el fondo. Si los objetos Compuesto representan rboles de anlisis, entonces las insttucciones
compuestas pueden ser instancias de un Compuesto cuyos hijos deben estar ordenados de mil
nera que renejen el programa.
Cu11ndo In ordenacin de los hijos es una cuesdn a 1ener en cuenta, debemos discnar las in-
tences de acceso y gestin de hijos cuidadosamente para conlrolar In secuencia de hijos. El
pa!Cn llerador (237) puede servimos de gufil.
.. ;
1:
1
1
...
r
'
''
Patrones Estructurales 157
7. Cach para mejorar el rendimiento. Si necesitamos recorrer composiciones o buscar en ellas
con .frecuencia, la clase Compuesto puede almacenar informacin sobre sus hijos que facilite
el recorrido o la b(isqueda, El Compuesto puede guardar resultados o simplemente informa-
cin que le permita evitar parte del recorrido o de la bsqueda. Por ejemplo. la clase Dibujo
del ejemplo de la seccin de Motivacin poda guardar la caja limtrofe de sus hijos. Mien-
tras se dibuja o es seleccionado, esta caja previamente guardada permite que Dibujo no tenga
que dibujar o realiz.ar bsquedas cuando sus hijos no son visibles en la ventano actual .
Los cambios en un componente nequerir.in inval idar la de sus padres. Esto funciona me-
jor cuando los componentes conocen 11 su!t podres. Por tanto, si se va a usar almacenamiento ca-
se necesita definir una intcd'az para decirle a los compuestos que su ya no es vlida.
8. Quin deberla borrar los componentt!s? En lenguajes sin recoleccin de basura, normal-
mente es mejor hacer que un Compuesto sea el responsable de borrar sus hijos cuando es des-
truido. Una n esta regla es cuando los objetos Hoja son inmutables y pueden por
tanto ser compartidos.
9. Cl es la mejor estructura de datos para almacenar los componentes? Los objetos Com-
puesto pueden usar muchns estructuras de datos diferentes para almacenar sus hijos, inclu
yendo listas enlazadas, rboles, arrays y tablas de dispersin. La eleccin de lo estrucrura de
datos depende (como siempre) de la eficiencia. De hecho, ni siquiera es necesario usar una es-
tructum de datos de propsito general. A veces los compuestos tienen una variable para cada
hijo, aunque esto requiere que cada subclase de Compuesto implemente su propia iiuerfaz de
gestin. Vase el patrn lnterpreter (225) para un ejemplo.
CDIGO DE EJEMPLO
Determinados equipos, como computadores y componentes suelen estar organizados en jerar-
quras de parte-todo o de pertenencia. Por ejemplo, un chasis puede contener unidades y placas base, un
bus puede contener tarjetas y un armario puede contener chasis. buses, etctera. Dichas estructuras pue-
den modelarse de manera natural con el palrn Composite.
Ll clase Equipo define una interf:12. para todos los equipos de la jerarqua de parte-todo.
cl ass Equipo {
public:
virtual -Equipo()
const char Nombre () { return _nombre
virtual Vatio Potencia()
virtual Moneda PrecioNeto()
virtual Moneda PrecioConOescuento()
virtual void Anadir(Equipo);
virtual void Eliminar(Equipo
virtual Iterador<Equipo > Crearltorador()
protected:
Equipo(const char):
private:
const char _nombre;
} i
Equipo decJara operaciones que devuelven los de un equipo, como su consumo y coste. Las
subclases implementan esw operaciones para determinados tipos de equipos. Equipo tambit!n decla-
ra una operncin Crearlterador que devuelve un Iterador (vase el Apt!ndice C) para acceder a sus
pQJ'tes. La implementacin predetennin:lda de esta operacin devuelve un IteradorNulo, que itera so.
bre el conjunto vado.
Las subclases d.e Equipo podran incluir clases Hoja que representen unidades de disco, circuitos
integrados e interruptores:
class DiSquetera : public Equipo { .
public:
} j
Disquetera(const char )
virtual -Disquetera()
virtual Vatio Potencia()
virtual Moneda PrecioNeto()
virt'ual Moneda Pre'cioConDescuento()
EquipoCompuesto es la clase base de los equipos que contienen otros equipos. E.s lambit!n una sub-
clase de Equipo.
'o
c.lass EquipoComp(es to : public Equipo
1
public: ./
virtual : -EquipoColllpuesto()
/
virtual Vatio Potencia()
virtual Uoneda PreciONetO()
virtual Moneda PrecioConOescuento()
virtual void Anadir(Equipo)
virtual void Eliinar(Equipo
virtual Iterador<Equipo > Crearlterador()i
protect'ed:
EquipoCompuesto(const char
private:
Lista<Equipo> _equipo;
} i
EquipoCompuesto define las operaciones para acceder a sus componentes y recorrerlos. Las operacio-
nes Anadir y Eli111inar insertan y borran equipos en la lista de equipos almacenados en el miembro
_equipo. La operacin Crearlterador devuelve un iterador (concretamente, una instancia de Itera
dorLista) para recorrer la lisia.
Una implementacin predeterminada de PrecioNeto podra usar Crearl terador para los
precios netos de los equipos que lo componcn:l
Moneda EquipoCompuesto::PrecioNeto () {
Iteradr<Equipo> i Crearlterador()
J Es fkit olvi\bl'IC de bocnr d itc:r.tdor urna vu que se h.:a us.:wJo. El pOLttn muc:stn. en la p.igina 24S, cmo protegerse con1u 11
lcsCI'f'Of'e.S.
r
.,
.!.
1
:

Moneda total e;
for (!>Primero() li>HaTerinado() i>Siguiente())
total+= i>EleentoAetual() >PrecioNeto()
delete i
retum total
Ahora podemos representar un chasis de computadora como una subclase de EquipoCo111puesto lla-
mada Chasis. Chasis hereda las operaciones relativas a los hijos de EquipoCopuesto.
class Chasis : public EquipoCompuesto
public:
}
Chasis(const char )
virtual -Chasis()
virt ual Vatio Potencia()
virtual Moneda PrecioNeto()
virtual Moneda PrecioConoeseuento()
Podemos delinir otros contenedores de equipos tales corno Armario y Bus de forma similar. Eso nos
da todo lo necesario para enSllmblar componentes en una computadora personal (bastante sencillo):
Armario ar11ario: new Armario(Arario de PC' );
Chasis chasis= new Chasis( ' Chasis de PC' )
armario>Anadir(ehasis)
Bus bus new Bus('Bus MCA' )
bus>Anadir(new Tarjeta( ' Token Ring de 16 Mbs 'lli
chasis>Anadir(bus)
chasis>Anadir(new Oisquetera( ' Disquetera de 3,5 pulgadas' ))
cout << ' El precio neto es << chasis >PreciONeto() << endl;
USOS CONOCIDOS
Se pueden encontrar ejemplos del patrn Composite Cf1 casi lodos los sistemas orientados a obj etos.
La clase original del ModeloNista/Controlador de Smalllalk (KP88} era un Compuesto, y prc
ticnrnente todos los toolkils o frameworks de interfaces de usuario han seguido sus pasos, induycndo
ET++ (con VObjec!S [WGM88]) e lnterViews (Styles [LCI+92]. Graphics [VL88) y Glyphs (CL90)}.
Merece pena destacar que la Vista original del ModeloNista/Conlrolador tena un conjunto de sub
vistas; en otras palabras, la clase View era tanto la clase Componente como la Compuesto. La versin
4.0 de Smalltalk-80 revis el Modelo/Vista/Controlador con una clase VisuaJComponenl que tena co
mo subclases View y CompositeView.
lV l"atrones ao Ulseno
El framework para compiladores de Smalltalk RTL [JML92j hace un uso intensivo del patrn
Composite. RTLExpresson es una clase Componente para rboles de anlisis. 1ene subclases, tales
como Bi nruyExprcssion, que contienen objetos RTtExpresson como hijos. Dichas clases definen una
estructura compuesta para rboles de anlisis. RegisterTransfer es la clase Componente para un pro-
grama en la forma intermedia de Single Statc Assgnment (SSA). Las subclases Hoja de Register-
Transfer definen dif-erentes asignaciones estticas, como
asignaciones primitivas que realitan una operacin en dos registros y asignan el resultado a un
tercero;
una asignacin con un registro fuente pero sin registro destino, que indica que el registro se usa
despus del retomo de una rutina; y
una asignacin con un registro destino pero sin origen, lo que indica que al registro se le asigna
un valor antes de que empiece la rutina.
Otra subclase, RegisterTransferSet, es una clase Compuesto que representa asignaciones que modli-
can varios registros a la vez.
Otro'ejemplo de este patrn tiene lugar en el dominio de las finanzas, donde una cartera de accio-
nes agrupa valores individuales. Se pueden permitir agregaciones complejas de valores implementan-
do una cartera como un Compuesto que se ajusta a la interfaz de un valor individual [BE93).
El patrn Command (215) describe cmo se pueden componer y secuenciar objetos Orden con
clase Compuesto Orden Macro.
1
PATRONES RELACIONADOS

1
Muchas veces se el enlace al componente padre para implementar el patrn Chain of Responsib -
lity (205).
El patrn Decorator (161) suele usarse junto con el Composte. Cuando se usan juntos decorado-
res y compuestos, normalmente ambos tendrn una clase p:.dre comn. Por t:.nto, los decomdores ten-
drn que admitir la interfaz Componente con operaciones como A nadir, Eliminar y ObtenerHijo.
El patrn Flyweight ( 1 79) permite comparti r componentes, si bien en ese caso stos ya no pueden
referirse a sus padres.
. Se puede ,usar el patrn lterator (237) para recorrer las estructuras definidas por el Compo-
stte.
El patrn' Visitar (305) localiza operaciones y cornportnmiento que de otro modo estarfa distribui -
do en varas clases Compuesto y Hoja.
1
1'
l .
r
. !
'
l
!"'
l
0ECORATOR
{DECORADOR)
PROPSITO
Patrones Estructurales 161
Estructural de Objetos
Asigna responsabilidades adicionales a un objeto dinmicamente, proporcionando una alternativa fle-
xible a la herencia para extender la funcionalidad.
TAMBIN CONOCIDO COMO
Wrapper (Envoltorio)
MOTIVACIN
A veces queremos ai'ladir responsabilidades a objetos individuales en vez de a toda una clase. Por
ejemplo, un toolkit de interfaces de debera permitir a:.dir propiedades (como bordes) o com-
ponamientos (como capacidad de desplazamiento) a cualquier componente de la interfaz. de usuario.
Un modo de ai'ladir responsabilidades es a travs de la herencia. Heredar un borde de otra clase
pondra un borde alrededor de todas las instancias de la subclase. Sin embargo, esto es inflexible., ya
que la eleccin del borde se hace estticamente. Un cliente no puede controlar cmo y cundo deco-
rar el componente con un borde.
Un enfoque ms flexi ble es encerrar el componente en otro objeto que ai'lada el borde. Al objeto
confinante se le denomina El decorador se ajusta a la interfaz del componente que decora
de manera que su presencia es transp3Iente a sus clientes. El decorador reenva las peticiones al com-
ponente y puede realizar acciones adicionales (tales como dibujar un borde) antes o despus del reen
vro. Dicha transparencia permite anidar decoradores recursivamente, pemtiendo asr un nmero
ilimitado de responsabilidades aadidas.
unDecoradorBorde
unDecoradorDespla%amlenlo
unaVlstaTexto
s-'('PO<ado011 -14 l>uofto
r ram ""' objr.cta co IPOlklwocq
N pc(C thW(\l fKdOMJtlJ, b\lt
111 6nir fpptoff wauld he
prolliblli l>dy UpeNive,
f\w.,acale, docloU'MM uf,
lhclrlut rormaa.
tOme
U1cftC.
wp shon: ol wla, obju lo
()
tq:WCICMuct. e:hlni:Jct tnd

cbc.f-stkvdilhc
Te-" anJ I""J)hk:a
could be tn:Med u i(cwmlylth
()

Potrebbero piacerti anche