Está en la página 1de 13

Composite

El patrón Composite sirve para construir algoritmos u objetos complejos a partir de otros más
simples y similares entre sí, gracias a la composición recursiva y a una estructura en forma de
árbol. Dicho de otra forma, permite construir objetos complejos componiendo de forma
recursiva objetos similares en una estructura de árbol. Esto simplifica el tratamiento de los
objetos creados, ya que al poseer todos ellos una interfaz común, se tratan todos de la misma
manera.

Este patrón busca representar una jerarquía de objetos conocida como “parte-todo”, donde se
sigue la teoría de que las "partes" forman el "todo", siempre teniendo en cuenta que cada
"parte" puede tener otras "parte" dentro.

Se debe utilizar este patrón cuando:

Se busca representar una jerarquía de objetos como “parte-todo”.

Se busca que el cliente puede ignorar la diferencia entre objetos primitivos y compuestos (para
que pueda tratarlos de la misma manera).

Diagrama UML

Component: implementa un comportamiento común entre las clases y declara una interface
de manipulación a los padres en la estructura recursiva.
Leaf: representa los objetos “hoja” (no poseen hijos). Define comportamientos para objetos
primitivos.
Composite: define un comportamiento para objetos con hijos. Almacena componentes hijos.
implementa operaciones de relación con los hijos.
Cliente: manipula objetos de la composición a través de Component.
Los clientes usan la interfaz de Component para interactuar con objetos en la estructura
Composite. Si el receptor es una hoja, la interacción es directa. Si es un Composite, se debe
llegar a los objetos “hijos”, y puede llevar a utilizar operaciones adicionales.
Ejemplo

Vamos a realizar un ejemplo de un Banco. Un banco puede tener muchos sectores: Gerencia,
Administrativo, RRHH, Cajas, etc. Cada uno de estos sectores tendrá empleados que cobran un
sueldo. En nuestro caso utilizaremos el Composite para calcular la sumatoria de sueldos de la
empresa. Para ello definimos la Interface y el Composite.

En la clase Composite está todo el secreto del patrón: contiene una colección de hijos del tipo
ISueldo que los va agregando con el método agrega(ISueldo) y cuando al composite le ejecutan
el getSueldo() simplemente recorre sus hijos y les ejecutas el método. Sus hijos podrán ser de
2 tipos: Composite (que a su vez harán el mismo recorrido con sus propios hijos) u Hojas que
devolverán un valor.
En nuestro ejemplo hay varios sectores, solo pongo uno para no llenar de pics el ejemplo. Pero
todos son muy parecidos: la única relación que tienen con el composite es que heredan de él.

Ahora veamos el caso del empleado que trabaja en el banco (sería una hoja):

Listo, ahora veamos la forma de concatenar todo. Yo lo hice en el Main (que vendría a
representar al cliente), pero en realidad el armado del banco no siempre lo debe hacer el
cliente. De hecho, podríamos utilizar un patrón creacional para que nos ayude en el armado.

El banco se compone de varios sectores, los cuales pueden tener personas o más sectores
adentro.

Consecuencias.

Define jerarquías entre las clases.

Simplifica la interacción de los clientes.

Hace más fácil la inserción de nuevos hijos.

Hace el diseño más general.

Si la operación es compleja, puede ensuciar mucho el código y hacerlo ilegible.

Temas a tener en cuenta

Hay muchas formas de llevar a cabo este patrón. Muchas implementaciones implican
referencias explicitas al padre para simplificar la gestión de la estructura.
Si el orden de los hijos provoca problemas utilizar Iterator.Para borrar elementos les
recomiendo que un objeto elimine a sus hijos.
La mejor estructura para almacenar elementos depende de la eficiencia: si se atraviesa la
estructura con frecuencia se puede dejar información en los hijos.
Factory Method

Libera al desarrollador sobre la forma correcta de crear objetos. Define la interfaz de creación
de un cierto tipo de objeto, permitiendo que las subclases decidan que clase concreta
necesitan instancias.
Muchas veces ocurre que una clase no puede anticipar el tipo de objetos que debe crear, ya
que la jerarquía de clases que tiene requiere que deba delegar la responsabilidad a una
subclase.

Este patrón debe ser utilizado cuando:

Una clase no puede anticipar el tipo de objeto que debe crear y quiere que sus subclases
especifiquen dichos objetos.

Hay clases que delegan responsabilidades en una o varias subclases. Una aplicación es grande
y compleja y posee muchos patrones creacionales.

Diagrama UML.

Creator: declara el método de fabricación (creación), que devuelve un objeto de tipo Product.
ConcretCreator: redefine el método de fabricación para devolver un producto.
ProductoConcreto: es el resultado final. El creador se apoya en sus subclases para definir el
método de fabricación que devuelve el objeto apropiado.

Observer

Este patrón de diseño permite reaccionar a ciertas clases llamadas observadores sobre un
evento determinado.
Es usado en programación para monitorear el estado de un objeto en un programa. Está
relacionado con el principio de invocación implícita. La motivación principal de este patrón es
su utilización como un sistema de detección de eventos en tiempo de ejecución. Es una
característica muy interesante en términos del desarrollo de aplicaciones en tiempo real.

Debe ser utilizado cuando:

Un objeto necesita notificar a otros objetos cuando cambia su estado. La idea es encapsular
estos aspectos en objetos diferentes permite variarlos y reutilizarlos independientemente.
Cuando existe una relación de dependencia de uno a muchos que puede requerir que un
objeto notifique a múltiples objetos que dependen de él cuando cambia su estado.

Este patrón tiene un uso muy concreto: varios objetos necesitan ser notificados de un evento y
cada uno de ellos deciden como reaccionar cuando esta evento se produzca.
Un caso típico es la Bolsa de Comercio, donde se trabaja con las acciones de las empresas.
Imaginemos que muchas empresas estan monitoreando las acciones una empresa X.
Posiblemente si estas acciones bajan, algunas personas esten interesadas en vender acciones,
otras en comprar, otras quizas no hagan nada y la empresa X quizas tome alguna decisión por
su cuenta. Todos reaccionan distinto ante el mismo evento. Esta es la idea de este patrón y son
estos casos donde debe ser utilizado.

Diagrama UML

Subject: conoce a sus observadores y ofrece la posibilidad de añadir y eliminar observadores.


Posee un método llamado attach() y otro detach() que sirven para agregar o remover
observadores en tiempo de ejecución.
Observer: define la interfaz que sirve para notificar a los observadores los cambios realizados
en el Subject.
SubjectConcreto: almacena el estado que es objeto de interés de los observadores y envía un
mensaje a sus observadores cuando su estado cambia.
ObserverConcreto: mantiene una referencia a un SubjectConcreto. Almacena el estado del
Subject que le resulta de interés. Implementa la interfaz de actualización de Observer para
mantener la consistencia entre los dos estados.

Facade

Busca simplificar el sistema, desde el punto de vista del cliente, proporcionando una interfaz
unificada para un conjunto de subsistemas, definiendo una interfaz de nivel más alto. Esto
hace que el sistema sea más fácil de usar.
Este patrón busca reducir al mínimo la comunicación y dependencias entre subsistemas. Para
ello, utilizaremos una fachada, simplificando la complejidad al cliente. El cliente debería
acceder a un subsistema a través del Facade. De esta manera, se estructura un entorno de
programación más sencillo, al menos desde el punto de vista del cliente (por ello se llama
"fachada").

Se debe utilizar cuando:

Se quiera proporcionar una interfaz sencilla para un subsistema complejo.

Se quiera desacoplar un subsistema de sus clientes y de otros subsistemas, haciéndolo más


independiente y portable.

Se quiera dividir los sistemas en niveles: las fachadas serían el punto de entrada a cada nivel.
Facade puede ser utilizado a nivel aplicación.

Diagrama UML

Facade: conoce cuales clases del subsistema son responsables de una petición.
Delega las peticiones de los clientes en los objetos del subsistema.
Subsistema: manejar el trabajo asignado por el objeto Facade. No tienen ningún conocimiento
del Facade (no guardan referencia de éste).

Los clientes se comunican con el subsistema a través de la facade, que reenvía las peticiones a
los objetos del subsistema apropiados y puede realizar también algún trabajo de traducción.
Los clientes que usan la facade no necesitan acceder directamente a los objetos del sistema.

Command

Encapsula un mensaje como un objeto. Especifica una forma simple de separar la ejecución de
un comando, del entorno que generó dicho comando. Permite solicitar una operación a un
objeto sin conocer el contenido ni el receptor real de la misma. Si bien estas definiciones
parecen un tanto ambigüas, sería oportuno volver a leerlas luego de entender el ejemplo.
Este patrón suele establecer en escenarios donde se necesite encapsular una petición dentro
de un objeto, permitiendo parametrizar a los clientes con distintas peticiones, encolarlas,
guardarlas en un registro de sucesos o implementar un mecanismo de deshacer/repetir.

Se debe usar cuando:

Se necesiten colas o registros de mensajes.

Se deba tener la posibilidad de deshacer las operaciones realizadas.

Se necesite uniformidad al invocar las acciones.

Se quiera facilitar la parametrización de las acciones a realizar.

Se quiera independizar el momento de petición del de ejecución.

El parámetro de una orden puede ser otra orden a ejecutar.

Se busque desarrollar sistemas utilizando órdenes de alto nivel que se construyen con
operaciones sencillas (primitivas).

Se necesite sencillez al extender el sistema con nuevas acciones.

Lo que permite el patrón Command es desacoplar al objeto que invoca a una operación de
aquél que tiene el conocimiento necesario para realizarla. Esto nos otorga muchísima
flexibilidad: podemos hacer, por ejemplo, que una aplicación ejecute tanto un elemento de
menú como un botón para hacer una determinada acción. Además, podemos cambiar
dinámicamente los objetos Command.

Diagrama UML

Command: declara una interfaz para ejecutar una operación.


CommandConcreto: define un enlace entre un objeto “Receiver” y una acción. Implementa el
método execute invocando la(s) correspondiente(s) operación(es) del “Receiver”.
Cliente: crea un objeto “CommandConcreto” y establece su receptor.
Invoker: le pide a la orden que ejecute la petición.
Receiver: sabe como llevar a cabo las operaciones asociadas a una petición. Cualquier clase
puede hacer actuar como receptor.

El cliente crea un objeto “CommandConcreto” y especifica su receptor. Un objeto “Invoker”


almacena el objeto “CommandConcreto”. El invocador envía una petición llamando al método
execute sobre la orden.
El objeto “CommandConcreto”, invoca operaciones de su receptor para llevar a cabo la
petición.

Decorator

El patrón decorator permite añadir responsabilidades a objetos concretos de forma dinámica.


Los decoradores ofrecen una alternativa más flexible que la herencia para extender las
funcionalidades.
Es conocido como Wrapper (igual que el patrón Adapter).
A veces se desea adicionar responsabilidades a un objeto pero no a toda la clase. Las
responsabilidades se pueden adicionar por medio de los mecanismos de Herencia, pero este
mecanismo no es flexible porque la responsabilidad es adicionada estáticamente. La solución
flexible es la de rodear el objeto con otro objeto que es el que adiciona la nueva
responsabilidad. Este nuevo objeto es el Decorator.

Este patrón se debe utilizar cuando:

Hay una necesidad de extender la funcionalidad de una clase, pero no hay razones para
extenderlo a través de la herencia.

Se quiere agregar o quitar dinámicamente la funcionalidad de un objeto.

Dado que este patrón decora un objeto y le agrega funcionalidad, suele ser muy utilizado para
adicionar opciones de "embellecimiento" en las interfaces al usuario. Este patrón debe ser
utilizado cuando la herencia de clases no es viable o no es útil para agregar funcionalidad.
Imaginemos que vamos a comprar una PC de escritorio. Una estándar tiene un precio
determinado. Pero si le agregamos otros componentes, por ejemplo, un lector de CD, el precio
varía. Si le agregamos un monitor LCD, seguramente también varía el precio. Y con cada
componente adicional que le agreguemos al estándar, seguramente el precio cambiará. Este
caso, es un caso típico para utilizar el Decorator.

Diagrama UML
Component: define la interface de los objetos a los que se les pueden adicionar
responsabilidades dinámicamente.
ComponenteConcreteo: define el objeto al que se le puede adicionar una responsabilidad.
Decorator: mantiene una referencia al objeto Component y define una interface de acuerdo
con la interface de Component.
DecoratorConcreto: adiciona la responsabilidad al Component.

Decorator propaga los mensajes a su objeto Component. Opcionalmente puede realizar


operaciones antes y después de enviar el mensaje.

Bridge

Desacopla una abstracción de su implementación, de manera que ambas puedan variar de


forma independiente. ¿Que quiere decir exactamente esto? Una abstracción se refiere a un
comportamiento que una clase debería implementar, ya sea porque esta obligada por una
interface o una clase abstracta. Por otro lado, con implementación se refiere a colocarle lógica
a dicha obligación.
Con lo cual, este patrón permite modificar las implementaciones de una abstracción en tiempo
de ejecución. Básicamente es una técnica usada en programación para desacoplar la interface
de una clase de su implementación, de manera que ambas puedan ser modificadas
independientemente sin necesidad de alterar por ello la otra.

Cuando un objeto tiene unas implementaciones posibles, la manera habitual de


implementación es el uso de herencias. Muchas veces la herencia se puede tornar inmanejable
y, por otro lado, acopla el código cliente con una implementación concreta. Este patrón busca
eliminar la inconveniencia de esta solución.

Este patrón debe ser utilizado cuando:


Se desea evitar un enlace permanente entre la abstracción y su implementación. Esto puede
ser debido a que la implementación debe ser seleccionada o cambiada en tiempo de
ejecución.

Tanto las abstracciones como sus implementaciones deben ser extensibles por medio de
subclases. En este caso, el patrón Bridge permite combinar abstracciones e implementaciones
diferentes y extenderlas independientemente.

Cambios en la implementación de una abstracción no deben impactar en los clientes, es decir,


su código no debe tener que ser recompilado.

Se desea compartir una implementación entre múltiples y este hecho debe ser escondido a los
clientes.

Permite simplificar jerarquías demasiado pobladas.

Diagrama UML

Abstraction: define una interface abstracta. Mantiene una referencia a un objeto de tipo
Implementor.
RefinedAbstraction: extiende la interface definida por Abstraction
Implementor: define la interface para la implementación de clases. Esta interface no se tiene
que corresponder exactamente con la interface de Abstraction; de hecho, las dos interfaces
pueden ser bastante diferentes entre sí. Típicamente la interface Implementor provee sólo
operaciones primitivas, y Abstraction define operaciones de alto nivel basadas en estas
primitivas.
ImplementadorConcreto: implementa la interface de Implementor y define su implementación
concreta.

Abstraction emite los pedidos de los clientes a su objeto Implementor. El cliente no tiene que
conocer los detalles de la implementación.

Bridge
Desacopla una abstracción de su implementación, de manera que ambas puedan variar de
forma independiente. ¿Que quiere decir exactamente esto? Una abstracción se refiere a un
comportamiento que una clase debería implementar, ya sea porque esta obligada por una
interface o una clase abstracta. Por otro lado, con implementación se refiere a colocarle lógica
a dicha obligación.
Con lo cual, este patrón permite modificar las implementaciones de una abstracción en tiempo
de ejecución. Básicamente es una técnica usada en programación para desacoplar la interface
de una clase de su implementación, de manera que ambas puedan ser modificadas
independientemente sin necesidad de alterar por ello la otra.

Cuando un objeto tiene unas implementaciones posibles, la manera habitual de


implementación es el uso de herencias. Muchas veces la herencia se puede tornar inmanejable
y, por otro lado, acopla el código cliente con una implementación concreta. Este patrón busca
eliminar la inconveniencia de esta solución.

Este patrón debe ser utilizado cuando:

Se desea evitar un enlace permanente entre la abstracción y su implementación. Esto puede


ser debido a que la implementación debe ser seleccionada o cambiada en tiempo de
ejecución.

Tanto las abstracciones como sus implementaciones deben ser extensibles por medio de
subclases. En este caso, el patrón Bridge permite combinar abstracciones e implementaciones
diferentes y extenderlas independientemente.

Cambios en la implementación de una abstracción no deben impactar en los clientes, es decir,


su código no debe tener que ser recompilado.

Se desea compartir una implementación entre múltiples y este hecho debe ser escondido a los
clientes.

Permite simplificar jerarquías demasiado pobladas.

Diagrama UML

Abstraction: define una interface abstracta. Mantiene una referencia a un objeto de tipo
Implementor.
RefinedAbstraction: extiende la interface definida por Abstraction
Implementor: define la interface para la implementación de clases. Esta interface no se tiene
que corresponder exactamente con la interface de Abstraction; de hecho, las dos interfaces
pueden ser bastante diferentes entre sí. Típicamente la interface Implementor provee sólo
operaciones primitivas, y Abstraction define operaciones de alto nivel basadas en estas
primitivas.
ImplementadorConcreto: implementa la interface de Implementor y define su implementación
concreta.

Abstraction emite los pedidos de los clientes a su objeto Implementor. El cliente no tiene que
conocer los detalles de la implementación.

También podría gustarte