Sunteți pe pagina 1din 39

Patrones De Diseo en Java.

Catedrtico: Ana Mara Chvez Trejo Asignatura:


Chvez Lpez David 06010064 Ingeniera en Sistemas Computacionales

Estilos y Arq. De Software. IV Unidad

01/12/2011

Patrones de diseo en Java.

Los patrones de diseo son la base para la bsqueda de soluciones a problemas comunes en el desarrollo de software y otros mbitos referentes al diseo de interaccin o interfaces. Un patrn de diseo es una solucin a un problema de diseo. Para que una solucin sea considerada un patrn debe poseer ciertas caractersticas. Una de ellas es que debe haber comprobado su efectividad resolviendo problemas similares en ocasiones anteriores. Otra es que debe ser reutilizable, lo que significa que es aplicable a diferentes problemas de diseo en distintas circunstancias Objetivos de los Patrones. Los patrones de diseo pretenden:

Proporcionar catlogos de elementos reusables en el diseo de sistemas software. Evitar la reiteracin en la bsqueda de soluciones a problemas ya conocidos y solucionados anteriormente. Formalizar un vocabulario comn entre diseadores. Estandarizar el modo en que se realiza el diseo. Facilitar el aprendizaje de las nuevas generaciones de diseadores condensando conocimiento ya existente.

Asimismo, no pretenden:

Imponer ciertas alternativas de diseo frente a otras. Eliminar la creatividad inherente al proceso de diseo.

No es obligatorio utilizar los patrones, solo es aconsejable en el caso de tener el mismo problema o similar que soluciona el patrn, siempre teniendo en cuenta que en un caso particular puede no ser aplicable. "Abusar o forzar el uso de los patrones puede ser un error".

Patrones de Diseo en Java de tipo: Estructural. Patrn de Diseo Adapter Objetivo Una clase Adapter implementa una interfaz que conoce a sus clientes y proporciona acceso a una instancia de una clase que no conoce a sus clientes, es decir convierte la interfaz de una clase en una interfaz que el cliente espera. Un objeto Adapter proporciona la funcionalidad prometida por un interfaz sin tener que conocer qu clase se utiliza para implementar esa interfaz. Permite trabajar juntas a dos clases con interfaces incompatibles. Aplicacin Es til el patrn adaptador cuando: Se desea utilizar una clase existente, y su interfaz no coincide con la que es requerida para la solucin. Se desea crear una clase reutilizable que coopera con clases no relacionadas o

imprevistas, es decir, las clases que no tienen necesariamente interfaces compatibles Un adaptador de objeto se adapta a la interfaz de subclase padre. Estructura

A continuacin se muestra la estructura bajo la cual se rige el patrn de diseo, as como sus participantes.

Participantes Target Define la interfaz especfica del dominio que el cliente usa Cliente (SimpleAdapter) Colabora con los objetos para cumplir con la interfaz de Target Adaptado Define una interfaz existente que ayuda a la adaptacin Adapter Adapta la interfaz del Adaptee a la interfaz de Target Consecuencias Los adaptadores clase y objeto tienen diferentes ventajas y desventajas. Un adaptador de clase: Adapta el Adaptee al Destino comprometindose con una clase Adaptado en concreto. El adaptador permite reemplazar algunos de los comportamientos Adaptee, ya que este adaptador es una subclase. n adaptador de objeto: Permite a un solo Adaptador trabajar con muchos Adaptadores, es decir, el propio Adaptee y todas sus subclases. En consecuencia a lo mencionado con anterioridad se destacar los siguientes puntos importantes: El cliente y las clases Adaptee permanecen independientes unas de las otras. El patrn Adapter introduce una direccin adicional en un programa. Como cualquier otra direccin, contribuye a la dificultad implicada en la compresin del programa. Se utiliza una clase Adapter para determinar cul de los mtodos es de un objeto llama otro objeto.

Es importante destacar que el patrn sea til en otras situaciones considerando determinadas funciones por ejemplo: La cantidad de trabajo que el adaptador realiza depende de la similitud de la interfaz de destino con los Adaptadores. Con la construccin de la adaptacin de interfaz en una clase, se elimina la suposicin de que otras clases vean la misma interfaz, la adaptacin de interfaz permite incorporar una clase dentro de sistemas existentes que espera diferentes interfaces de la clase. Patrones con los que se relaciona. Facade La clase Adapter proporciona un objeto que acta como un intermediario para llamar a los mtodos entre los objetos cliente y uno de los otros objetos que no conocen a los objetos cliente. El patrn Facade proporciona un objeto que acta como un intermediario para llamar a los mtodos entre los objetos cliente y mltiples objetos que no conocen a los objetos cliente. Iterator El patrn Iterator es una versin especializada del patrn Adapter para acceder secuencialmente al contenido de una coleccin de objetos Proxy. El patrn Proxy, como el patrn Adapter, utiliza un objeto que es un sustituto por otro objeto. Sin embargo, un objeto proxy tiene la misma interaz que el objeto por el que se sustituye. Strategy El patrn Strategy es estructuralmente similar al patrn Adapter. La diferencia est en el objetivo. El patrn Adapter permite a un objeto cliente exportar su funcin deseada originalmente para llamar al mtodo de los objetos que implementan un interfaz particular. El patrn Strategy proporciona objetos que implementan un interfaz particular con el propsito de alterar o determinar el comportamiento de un objeto cliente.

Ejemplo de implementacin del patrn.

Vamos a plantear el siguiente escenario: nuestro cdigo tiene una clase Persona (la llamamos PersonaVieja) que se utiliza a lo largo de todo el cdigo y hemos importado un API que tambin necesita trabajar con una clase Persona (la llamamos PersonaNueva), que si bien son bastante similares tienen ciertas diferencias:

Nosotros

trabajamos

con

los

atributos

nombre,

apellido

fecha

de

nacimiento.

Sin embargo, la PersonaNueva tiene un solo atributo nombre (que es el nombre y apellido de la persona en cuestin) y la edad actual, en vez de la fecha de nacimiento.

Para esta situacin lo ideal es utilizar el Adapter. Para ello primero crearemos las 2 clases de Persona y sus correspondientes interfaces.

Y ahora se crea el Adapter.

Y se utiliza de esta ultima manera.

Patrn de Diseo Facade. Objetivo Simplifica los accesos a un conjunto de objetos relacionados proporcionando un objeto que todos los objetos fuera del conjunto utilizan para comunicarse con el conjunto. Define una interfaz de ms alto nivel que permite usar el sistema ms fcil.. Aplicacin

Se usa el patrn Facade cuando: Se pretende proveer una interfaz nica para un subsistema complejo. Esto ayuda a que un subsistema sea ms reutilizable y fcil de adaptar. Existen gran nmero de dependencias entre clientes y clases que implementan una abstraccin. Con el patrn Facade se desacopla el cliente del subsistema, as como entre subsistemas; esto promueve subsistemas independientes y portables. Se quiere dividir en capas su subsistema. Usar Facade para definir el punto de entrada a cada nivel del subsistema. Estructura

En la figura se muestra la estructura bajo la cual se rige el patrn de diseo, asi como sus participantes.

Participantes Facade: Conoce que clases son responsables de una peticin. Delega las peticiones del cliente a objetos del subsistema apropiados. Subsystem classes: implementa la funcionalidad del subsistema, maneja el trabajo asignado por facade. Desconocen a facade, lo que indica que no tienen referencia a este.

Colaboracin El cliente se comunica con el subsistema transmitiendo peticiones a facade, que se encarga, luego, de enviarlas a los objetos apropiados. Facade tambin puede realizar algn trabajo, debido a la traduccin de su interface a la interface que el subsistema posee. El cliente que utiliza facade no tiene acceso al subsistema directamente. Consecuencias Facade ofrece las siguientes ventajas: Protege al cliente de los componentes del subsistema, as reduce el nmero de objetos con los que el cliente se relaciona. Con ello se hace menos tedioso de usar al subsistema. Promueve un acoplamiento entre el cliente y el subsistema. Lo que permite modificar componentes en el subsistema sin modificar el cliente. No evita que se use clases del subsistema si la aplicacin la necesita. Colaboracin De forma general el cliente se comunica con el subsistema transmitiendo peticiones a Facade, que se encarga, luego, de enviarlas a los objetos apropiados. Tambin puede realizar algn trabajo, debido a la traduccin de su interface a la interface que el subsistema posee. El cliente que no tiene acceso al subsistema directamente.

10

Usos Conocidos.

El sistema compilador de smalltalk utiliza facade para agrupar clase como escner, flujos de datos y analizador de sintaxis. Tambin es utilizado para agrupar frameworks. En java las clases graphics y Font utilizan facade.

Patrones con lo que se relaciona

Abstract Factory Se utiliza Facade, para facilitar el acceso a las familias de objetos. Mediator Similar a Facade, pues este tambin abstrae la funcionalidad de clases existentes. Mediator intenta abstraer la comunicacin, entre una coleccin de objetos, as como sus comportamientos adicionales. La interfaz Facade se implementa como un Singleton para garantizar un punto de acceso nico al subsistema. Implementacin del patrn

Es til considerar los siguientes aspectos cuando se utiliza Facade: Reducir el acoplamiento entre un cliente y el subsistema. El acoplamiento se reduce incluso cuando Facade no es una interfaz sino una clase abstracta, Un subsistema encapsula clases hacindolas privadas; el uso de clases privadas restringe el acceso del cliente al subsistema directamente.

11

Aqu un ejemplo de la utilizacin del Patrn de diseo Facade.

import java.util.Calendar; import java.util.Formatter; import java.util.GregorianCalendar; /** Fachada */ public class FormatoFecha { private GregorianCalendar gcal; public FormatoFecha(String isodate_ymd) { String[] a = isodate_ymd.split("-"); gcal = new GregorianCalendar(Integer.parseInt(a[0]), Integer.parseInt(a[1])-1, Integer.parseInt(a[2])); } public void sumarDias(int dias) { gcal.add(Calendar.DAY_OF_MONTH, dias); } public String toString() { return String.format("%1$tY-%1$tm-%1$td", gcal); } }

Clase Cliente.
/** Cliente */ public class Cliente { public static void main(String[] args) { FormatoFecha d = new FormatoFecha("2011-05-15"); System.out.println("Fecha: "+d); d.sumarDias(15); System.out.println("15 das despus: "+d); } }

12

Patrn de Diseo Composite

Objetivo Es til en la construccin de objetos complejos por medio de la composicin recursiva de objetos similares. Dicho patrn tambin permite que los objetos del rbol se manipulen por un manejador consistente, para requerir todos los objetos hay una superclase o una interfaz comn. Asimismo compone objetos en estructura de rbol y los representa en jerarquas Todo- Parte. Dej a los usuarios manejar objetos simples y compuestos uniformemente. Motivacin

Los editores grficos permiten

a los usuarios trabajar con diagramas simples y

compuestos. Los usuarios crean grupos compuestos a partir de una lista de componentes, que se agrupan para formar componentes mayores. Una simple implementacin sera un grupo de clases que definen grficas primitivas tales como texto y lneas, y otras clases diferentes actan como contenedoras de estas primitivas; pero trabajar de esta manera genera un problema; un cdigo que use estas clase trabaja con objetos primitivos y compuestos por separado, an si la mayora de veces las trata idnticamente. Esta distincin hace ms complejo el sistema, el patrn de diseo Composite ofrece una forma de manejar objetos compuestos sin que el usuario tenga que hacer la distincin. La clave del patrn Composite es una clase abstracta, que es la clase padre tanto de objetos simples, como de compuestos. Esta clase incluye mtodos para objetos simples y tambin para los compuestos. Las clases primitivas (simples) no implementaran los mtodos de la clase abstracta que actan sobre los componentes de un objeto (porque son objetos simples); por su lado las clases contenedoras (compuestas), s trabajan todos los mtodos. En el patrn los objetos individuales (simples), son las hojas de un rbol, y los compuestos son nodos que contienen las hojas que se derivan de ellos .

13

Aplicabilidad Los clientes no conocen la diferencia entre los objetos individuales y los grupos de objetos compuestos, a fin de que los trate de forma genrica. Se cuenta con un objeto complejo que se necesita descomponer en una jerarqua de objetos que forman parte de todo Se minimiza la complejidad de las jerarquas minimizando el nmero de objetos hijos diferentes en el rbol que los objetos compuestos necesitan para formarse. Se desea representar jerarquas homogneas de los objetos. Se desea que los clientes podrn hacer caso omiso de la diferencia entre las

composiciones de objetos e individuales.Los clientes tratan todos los objetos de la estructura compuesta de manera uniforme. Estructura A continuacin se muestra la estructura bajo la cual se rige el patrn de diseo, asi como sus participantes.

14

Participantes Component: Determina la interfaz para la presentacin de los objetos de la composicin, as como el manejo de los componentes hijo, establece algunos comportamientos predefinidos para todas las clases segn su correspondencia. Leaf: Define la conducta de los objetos primitivos, otra de sus caractersticas es no tener hijos adems de aclarar el comportamiento explcito de cada objeto simple. Composite: Detalla el comportamiento de los objetos participantes que tienen los hijos, acumula a los hijos e implementa las operaciones de los componentes. Client: Emplea los objetos por medio de la interfaz proporcionada Component. Consecuencias Define las jerarquas de clase que consiste en objetos primitivos y objetos compuestos. Los objetos simples se descomponen en objetos complejos que a su vez estn compuestos, y as recursivamente. Cuando el cdigo cliente espera un objeto primitivo, puede tomar tambin un objeto compuesto. Hace que el cliente pueda tratar las estructuras de objetos compuestos e individuales de manera uniforme. Los clientes normalmente se estn tratando con una hoja o un objeto compuesto. Esto simplifica el cdigo de cliente, ya que evita tener que escribir en

etiquetas y funciones en las clases que definen la composicin.

Hace que sea ms fcil agregar nuevos tipos de componentes, que define las hojas de trabajo, compuestos o subclases automticamente con las estructuras existentes y el 15

cdigo de cliente. Los clientes no tienen que combinarse por nuevos componente de las clases. Colaboraciones

Los clientes utilizan la interfaz de componentes para interactuar con objetos en la estructura de materia compuesto. Si el receptor es una hoja, la solicitud se maneja directamente. Si el destinatario es un compuesto, por lo general reenva las solicitudes a los componentes de su hijo, posiblemente, realiza operaciones adicionales antes o despus de la expedicin. Los clientes utilizan la interfaz de clase para que los componentes los objetos. Patrones con los que se relaciona. Chain of Responsibility El patrn Chain of Resposibility se combinacon el patrn Composite para aadir enlaces del hijo al padre (para propagar responsabilidades hacia arriba), de tal forma que, los hijos consigan la informacin sobre un progenitor sin tener que conocer qu progenitor proporciona la informacin. Decorator Generalmente se usan juntos. Flyweight Para compartir componentes, cuando no haya referencias a los padres. Iterator Para recorrer los hijos en un Composite. Visitor Es util el patrn Visitor para encapsular operaciones en una clase simple, que de lo contrario podra propagarse a travs de muchas clases y agregar comportamiento a las clases del patrn Composite. interacten con

Implementacin del patrn Se consideran muchas situaciones cuando se implementa el patrn Composite: 16

Referencias explcitas a los padres. Si las clases que participan en el patrn Composite implementan alguna operacin por delegacin de estas a sus objetos padre, entonces el mejor modo para observar velocidad y simplicidad es teniendo en cada instancia del Componente Abstracto una referencia a su padre. Compartir componentes. Es importante implementar el puntero al padre de una forma que se asegure la consistencia entre padre e hijo. Siempre un Componente Abstracto identifique a un Composite Abstracto como su padre, si y slo si, el Composite Abstracto lo identifica como uno de sus hijos. Declarar las operaciones de manejo de hijos. La forma de obligar esto es modificar las referencias al padre y al hijo solamente en la clase Composite Abstracto aadiendo y quitando mtodos. El lugar habitual para definir la referencia de los padres est en la clase de componentes. Las clases compuestas heredan la referencia y las operaciones que se gestionan.

Ejemplo de Aplicacin del Patrn Composite. El patrn Composite da una solucin elegante a este problema, de la que adems resulta en una implementacin ms sencilla. A la clase Figura la llamaramos Grfico y de ella extenderan tanto Crculo, Cuadrado y Tringulo, como GrupoDeImgenes. Adems, sta ltima tendra una relacin todo-parte de multiplicidad * con Grfico: un GrupoDeImgenes contendra varios Grficos, ya fuesen stos Cuadrados, Tringulos, u otras clases GrupoDeImgenes. As, es posible definir a un grupo de imgenes recursivamente. Por ejemplo, un objeto cuya clase es GrupoDeImgenes podra contener un Cuadrado, un Tringulo y otro GrupoDeImgenes, este grupo de imgenes podra contener un Crculo y un Cuadrado. Posteriormente, a este ltimo grupo se le podra aadir otro GrupoDeImgenes, generando una estructura de composicin recursiva en rbol, por medio de muy poca codificacin y un diagrama sencillo y claro.

17

Diagrama UML

Clase Componente.
import java.util.*; public abstract class Componente { protected String nombre; public Componente (String nombre) { this.nombre = nombre; } abstract public void Agregar(Componente c); abstract public void Eliminar(Componente c); abstract public void Mostrar(int profundidad); }

18

Clase Compuesto
class Compuesto extends Componente { private ArrayList<Componente> hijo = new ArrayList<Componente>(); public Compuesto (String name) { super(name); } @Override public void Agregar(Componente componente) { hijo.add(componente); } @Override public void Eliminar(Componente componente) { hijo.remove(componente); } @Override public void Mostrar(int profundidad) { System.out.println(nombre + " nivel: " + profundidad); for (int i = 0; i < hijo.size(); i++) hijo.get(i).Mostrar(profundidad + 1); } }

Clase Hoja
class Hoja extends Componente { public Hoja (String nombre) { super(nombre); } public void Agregar(Componente c) { System.out.println("no se puede agregar la hoja"); } public void Eliminar(Componente c) { System.out.println("no se puede quitar la hoja"); } public void Mostrar(int depth) { System.out.println('-' + "" + nombre); } }

19

Clase Cliente
public class Client { public static void main(String[] args) { Compuesto raiz = new Compuesto("root"); raiz.Agregar(new Hoja("hoja A")); raiz.Agregar(new Hoja("hoja B")); Compuesto comp = new Compuesto("compuesto X"); comp.Agregar(new Hoja("hoja XA")); comp.Agregar(new Hoja("hoja XB")); raiz.Agregar(comp); raiz.Agregar(new Hoja("hoja C")); Hoja l = new Hoja("hoja D"); raiz.Agregar(l); raiz.Eliminar(l); raiz.Mostrar(1); } }

20

Patrn de Diseo Bridge Intencin u objetivo Es til cuando hay una jerarqua de abstracciones y la correspondiente jerarqua de implementaciones. Ms que combinar las abstracciones e implementaciones en muchas clases distintas, el patrn Bridge implementa las abstracciones e implementaciones como clases independientes para ser combinados dinmicamente. Es decir, desacopla una abstraccin de su implementacin y les permite variar independientemente. Aplicacin Utilizar el patrn Bridge cuando:

Se quiere evitar la vinculacin entre la abstraccin y la implementacin .Esto es debido a que la implementacin es seleccionada o cambiada en tiempo de ejecucin.

La abstraccin e implementacin tienen que ser extendibles por las subclases. Un Bridge permite ampliar de forma independiente las abstracciones e implemetaciones esto no causa ningn efecto de la aplicacin con esto se evita que los clientes no noten los multiples objetos en la implementacin.

Estructura A continuacin en la figura se muestra la estructura bajo la cual se rige el patrn de diseo, as como sus participantes.

21

Los Participantes : Abstraction:

Define la abstraccin de la interfaz, manteniedo una referencia a un objeto que implementa la interfaz.

RefinedAbstraction:

Ampla la interfaz definida por la abstraccin, de modo que captura las especificaciones o informacin necesaria proveniente del objeto que implementa la interfaz.

Implementor:

Define la interfaz de la aplicacin clases. Esta interfaz no tiene que corresponder exactamente a la interfaz de abstraccin, de hecho las dos interfaces pueden ser muy diferentes. Normalmente la interfaz Implementor proporciona slo operaciones primitivas, y define la abstraccin de alto nivel sobre la base de estas operaciones primitivas.

ConcreteImplementor:

Implementa la interfaz concreta y define sus aplicaci

Client:

Utiliza los objetos proporcianados por sus gusto.

Consecuencias Separa la interfaz de la aplicacin: las aplicaciones no estn relacionadas siempre con la interfaz. Dicha caracterstica es muy til cuando se garantiza la compatibilidad entre diferentes bibliotecas de clases. Se protege la implementacin a los clientes y el mecanismo de acompaamiento. Mejora la extensibilidad, para de esta forma ampliar la abstraccin y ejecucin de jerarquas independientes.

22

Colaboraciones

La abstraccin enva las peticiones del cliente a su objeto Implementor. Patrones con los que se Relaciona Abstract Factory Crear y configurar un bridge en particular. Adapter Tiene una estructura similar pero su intencin es diferente. El patrn bridge separa la abstraccin de la implementacin de un componente, permitiendo que sean modificados independientemente, mientras adapter reutiliza un componente ya existente que no es compatible. Implementacin del patrn.

En el siguiente ejemplo, se lleva a cavo la solicitud de un pedido en una panadera, donde el cliente elige el diferente tipo de pan que hay disponible. //nuestra clase Abstraction, su mtodo permite obtener el tipo de pan del pedido// package Logica; public abstract class Panaderia { public abstract TipoDePan getImplementador(); public abstract String nombrePan(); } //*Ahora creamos una clase que hereda de Panaderia, en la cual se estructura el metodo de la clase abstracta y se crean nuevos metodos, los cuales trabajan con un objeto de la que implementa la interfaz*//

23

package Logica; public class Panes extends Panaderia { private TipoDePan pan; public String nombrePan() { return pan.tipoPan(); } public void setInterfaz(TipoDePan tipoInterfaz) { pan = tipoInterfaz; } public TipoDePan getImplementador() { return pan; } } // Creamos la interfaz// package Logica; public interface TipoDePan { public abstract String tipoPan(); } //*Ahora se crean las clases de los diferentes tipos de pan disponibles sobreescribiendo el mtodo implementado de la interfaz*// package Logica; public class PanDeFrutas implements TipoDePan { public String tipoPan() { return "Pan de Frutas"; } } package Logica; public class PanIntegral implements TipoDePan { public String tipoPan() { return "Pan integral"; } } package Logica; public class PanLight implements TipoDePan { public String tipoPan() { return "Pan Light"; } } Por ltimo tenemos la vantana donde el cliente podra seleccionar y obtener su pedido: package Interfaz; import Logica.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; public class Pedido extends JFrame implements ActionListener { //atributos de la clase// Panaderia panaderia ; private JButton panIntegral; private JButton panLight; private JButton panDeFrutas;

24

private JLabel suOrden; //constructor de la clase, e inicializamos y ubicamos los atributos// public Pedido(){ this.setSize(400,300); this.setLayout(null); this.setDefaultCloseOperation(Pedido.DISPOSE_ON_CLOSE); this.setTitle(":::Panaderia:::"); suOrden = new JLabel(); suOrden.setSize(300,100); suOrden.setLocation(30, 20); suOrden.setText("Seleccione su Pan :"); this.getContentPane().add(suOrden); panIntegral = new JButton(); panIntegral.setSize(110, 30); panIntegral.setLocation(10, 100); panIntegral.setText("pan Integral"); this.getContentPane().add(panIntegral); panIntegral.addActionListener(this); panLight = new JButton(); panLight.setSize(110, 30); panLight.setLocation(130, 100); panLight.setText("pan Light"); this.getContentPane().add(panLight); panLight.addActionListener(this); panDeFrutas = new JButton(); panDeFrutas.setSize(120, 30); panDeFrutas.setLocation(250, 100); panDeFrutas.setText("pan De Frutas"); this.getContentPane().add(panDeFrutas); panDeFrutas.addActionListener(this); } //manupula el objeto segun la especificacion del cliente// @Override public void actionPerformed(ActionEvent e) { //inicializa un objeto de la clase Panes// Panes pan= new Panes(); if (e.getSource() == panDeFrutas) { //reliza la implemntacion pasando en su mtodo el tipo de pan que se eligi// pan.setInterfaz(new PanDeFrutas()); } if (e.getSource() == panLight) { pan.setInterfaz(new PanLight()); } if (e.getSource() == panIntegral) { pan.setInterfaz(new PanIntegral()); } //se presenta al cliente el pedido como tal// suOrden.setLocation(100, 130); suOrden.setText("Su orden es : " + pan.nombrePan()); } }

25

Patrn de Diseo Proxy Objetivo Es un patrn muy general que ocurre en muchos otros patrones, pero nunca l mismo en su puro estado. El patrn Proxy hace llamadas a mtodos de un objeto que ocurre indirectamente a travs de un objeto proxy que acta como un sustituto para otro objeto, delegando las llamadas a mtodos a ese objeto. Las clases para los objetos proxy se declara de una forma que

normalmente eliminan el conocimiento de los objetos del cliente que se tratan con un proxy. Es decir, este patrn provee un representante de acceso a otro objeto. Aplicacin

Es til cuando se hace una referencia verstil a un objeto. Existen varias situaciones comunes en las que se aplica el patron Proxy por ejemplo: Para representar un objeto local. Para objetos pesados por demanda. Control de entrada a un objeto. Para sustituir un punto basico de acceso en la realizacin de cambios para acceder al objeto.

26

Estructura

Aqu se muestra la estructura bajo la cual se rige el patrn de diseo, as como sus participantes.

Participantes Proxy: Tiene una referencia que permite al Proxy acceder el objeto, proporciona la interfaz similar a la del sujeto, de forma que un Proxy que puede llegar a ser sustituido. Adems de mantener la referencia al objeto RealSubject, tiene una interfaz idntica a la de Subject as un proxy puede sustituirse por un RealSubject, y controla el acceso al RealSubject y puede ser el responsable de su creacin y borrado. Subject: Delimita la interfaz comn para el RealSubject y Proxy de tal forma que tenga la posibilidad de utilizar un Proxy en cualquier sitio en el que se espere un RealSubject. RealSubject: Define el objeto real que Proxy representa.

27

Client: Quien desea acceder al objeto. Consecuencias El patrn Proxy introduce un nivel de indireccion al acceder a un objeto. La direccin adicional tiene muchos usos, dependiendo del tipo de Proxy: Un proxy remoto oculta el hecho de que un objeto se encuentra en un espacio de direcciones diferentes. Un proxy virtual realiza optimizaciones como la creacin de un objeto bajo demanda. Tanto las delegaciones de proteccin y las referencias inteligentes permiten ms tareas de mantenimiento cuando un objeto es acceder a ella. Colaboraciones Proxy reenva las solicitudes del sujeto real, cuando proceda, en funcin del tipo de Proxy. Patrones relacionados Un Proxy no tiene que conocer el tipo de un sujeto real y puede acceder a l a travs de la interfaz abstracta. Se pueden utilizar facilidades de los lenguajes para implementarlo. Bridge Un Proxy slo tiene una implementacin, y un Bridge puede tener ms de una. Proxy se suele usar para controlar el acceso a su implementacin, el Bridge implementacin dinmicamente. Adapter Proporciona una interfaz diferente al objeto que adapta, pero el Proxy tiene la misma interfaz Aunque el Proxy puede reutilizar una operacin (as su interfaz puede verse como un subconjunto). Decorador Se puede implementar de manera similar al Proxy pero el propsito es diferente: el public interface Soporte { public void escribir( String mensaje ); 28 permite cambiar una

public String leer( int numLinea ); public Vector leer(); } Decorador aade responsabilidades a un objeto, el Proxy slo controla su acceso. Ejemplo: Tenemos un interface para escribir y leer de un soporte:

Adems tenemos una clase, denominada Pizarra, que implementa el interface Soporte y que en su mtodo escribir(String mensaje) simplemente aade el argumento a un Vector. El mtodo leer(int numLinea) devuelve la cadena cuyo orden dentro del vector es el argumento. El cliente (main) pueda insertar (escribir) y obtener (leer) cadenas.

import java.util.*; public class Pizarra implements Soporte { private Vector mensajes = new Vector(); public void escribir(String mensaje) { mensajes.add(mensaje); } public String leer(int numLinea) { return mensajes.get(numLinea); } public Vector leer() { return mensajes; } } El proxy es un intermediario (que tambin implementa el interface del objeto real) y que nos permite aadir o modificar comportamiento sin reescribir el objeto real. En escribir() del proxy aado el nmero de lnea y delega en la Pizarra el resto de comportamiento. Es interesante observar que este patrn evita abusar del uso de herencia. Este abuso es la primera tentacin del novato, ya que piensa: "si quiero modificar el comportamiento de una clase hago el nuevo comportamiento en una clase hija". No es que la herencia sea de partida ilegal o inconveniente, simplemente se trata de no abusar de ella aplicandola a todo tipo de problema. De esta forma no caeremos en el vicio de aquel que slo saba usar martillos y todos los problemas le parecan clavos.

29

import java.util.Vector; public class ProxyDePizarra implements Soporte { private Soporte soporte; public ProxyDePizarra() { this.soporte = new Pizarra(); } public ProxyDePizarra( Soporte soporte) { this.soporte = soporte; } public void escribir( String mensaje ) { String linea = String.valueOf(soporte.leer().size()+1) + " " + mensaje; soporte.escribir( linea ); } public String leer( int numLinea ) { return soporte.leer( numLinea ); } public Vector leer() { return soporte.leer(); } } Un aspecto importante del cliente es que slo utiliza el tipo Interface Soporte para acceder al proxy, con lo que conseguimos generalidad:

public class Inicio { static public void main(String[] args) { try { //// Creamos el proxy Soporte proxy = Factoria.getPizarra("ProxyDePizarra"); //// Escribimos (el proxy inserta nmero de lnea) proxy.escribir("En un lugar de La Mancha"); proxy.escribir("de cuyo nombre no quiero acordarme"); for (String str : proxy.leer()) Visor.mostrar(str); } catch (Exception e) { e.printStackTrace(); } } } La factoria simple es otro patrn importante. Una factora se centra en ocultar la instanciacin de una clase. En nuestro caso anterior devuelve un objeto del tipo ProxyDePizarra: 30

/******************************************************************************* ***** * Factoria de pizarra (objeto real o proxy). Recibe el nombre de la clase * (sin especificar paquete) y crea y devuelve el objeto (real o proxy). ******************************************************************************** ***/ public class Factoria { static public Soporte getPizarra( String nomClase ) throws Exception { Class clase = Class.forName( Factoria.class.getPackage().getName() + "." + nomClase); return (Soporte) clase.newInstance(); } } Nota: Para que el newInstance() de la Factoria pueda funcionar debe existir un constructor sin argumentos en el ProxyDePizarra. El visor es algo elemental, tan slo sirve para diferenciar el modelo de la vista:

public class Visor { static public void mostrar( String mensaje ) { System.out.println( mensaje ); } } El resultado final sera:

1 En un lugar de La Mancha 2 de cuyo nombre no quiero acordarme

31

Otras caractersticas El proxy y el objeto real comparten interface. El proxy debe tener una referencia al objeto real.

Ya hemos dicho que el proxy es un intermediario que implica un recubrimiento del objeto real para aadir o modificar comportamiento. Especialmente apropiado cuando estamos en situaciones en las que tenemos que elegir entre las operaciones del objeto real y las del proxy. Aunque en el ejemplo anterior no hacemos instancia del objeto real ni permitimos ningn acceso directo a l, podriamos tener dos tipos de acceso: uno directo al objeto real y otro al proxy.

Soporte piz = Factoria.getPizarra("Pizarra"); Soporte proxy = new ProxyDePizarra(piz); piz.escribir("XYZ"); // NO aade n de lnea proxy.escribir("QQQ"); // SI aade n de lnea

32

Patrn de Diseo Chain of Responsability Intencin u objetivo

Permite a un objeto enviar un comando sin conocer qu objeto u objetos lo recibirn, evitando el acoplamiento entre el que enva y el que recibe una peticin. Esto permite el paso del comando a un objeto de la cadena que es parte de una gran estructura. Cada objeto de la cadena podra manejar el comando, pasar el comando al siguiente objeto de la cadena, o las dos cosas. Aplicacin

Usar el patrn de la cadena de responsabilidad cuando: Ms de un objeto maneja una peticin, y el controlador no se sabe Apriori. El

controlador se determina de forma automtica. Se desea remitir una peticin a uno de varios objetos sin especificar el receptor de forma explcita. La cadena de la responsabilidad del conjunto de objetos que puede manejar una solicitud se especifica de forma dinmica. Estructura Aqu se muestra la estructura bajo la cual se rige el patrn de diseo, asi como sus participantes.

33

Una estructura de objetos tpicos podra tener este aspecto:

Paticipantes

Cliente: Es el encargado de generar las peticiones que pasaran por el Handler (manejador) genrico. Handler (Manejador): Est compuesto por un interfaz donde se desarrollan las peticiones que genera el cliente. ManejadorConcreto: Manipula la peticin que le corresponda del cliente. Consecuencias Cadena de Responsabilidad tiene los siguientes beneficios: Reduccin del acoplamiento El patrn libera un objeto al saber que otro objeto controla una solicitud. Slo un objeto tiene que saber que atendern las peticiones "de manera apropiada." Tanto el receptor como el remitente no tienen conocimientos explcitos de cada uno, y un objeto en la cadena no tiene por qu saber acerca de la estructura de la cadena. Como resultado, la

cadena de responsabilidad puede simplificar las interconexiones del objeto.

Mayor flexibilidad en la asignacin de responsabilidades a los objetos

34

Agrega la flexibilidad en la distribucin de responsabilidades entre los objetos. Se agregan o cambian las responsabilidades para el manejo de una solicitud mediante la adicin de cualquier otro modo de cambiarse la cadena en tiempo de ejecucin. Se combinan esto con sus subclases de la especializacin de controladores en forma esttica.

La recepcin no est garantizada La solicitud puede no ser controlada cuando la cadena no este configurada correctamente.

Colaboraciones Cuando un cliente emite una solicitud, sta se propaga a lo largo de la cadena hasta que un objeto Concrete Handler asume la responsabilidad de su manejo. Patrones relacionados Composite Se relaciona con el ya que el patrn Chain of Responsability permite la relacin entre el padre y el hijo, sin que este sepa de qu progenitor est obteniendo la informacin. Implementacin. Ejemplo:
public class ChainOfResponsabilityPattern { public void main(String args[]){ new A("C"); } public abstract class Letter{ String letter; abstract public void checkLetter(); } public class A extends Letter{ public A(String letter){ this.letter = letter; checkLetter(); } public void checkLetter() { if(!letter.equals("A")){ new B(letter);//Next Chain }

35

else{ System.out.print("Here we have " + letter); } } } public class B extends Letter{ public B(String letter){ this.letter = letter; checkLetter(); } public void checkLetter() { if(!letter.equals("B")){ new C(letter);//Next Chain }else{ System.out.print("Here we have " + letter); } } } public class C extends Letter{ public C(String letter){ this.letter = letter; checkLetter(); } public void checkLetter() { if(letter.equals("C")){ System.out.print("Check with numbers dude!!"); } } }

El siguiente cdigo java muestra un ejemplo de este patrn para una clase que hace un 'log'. Cada elemento de log decide si debe de mostrar el log dependiendo de su nivel de log y pasa el mensaje al siguiente elemento. La salida ser:
Escribiendo Escribiendo Escribiendo Escribiendo Enviando un Escribiendo en DEBUG: Entrando en function y. en DEBUG: Paso 1 completado en STDERR: Paso 1 completado. en DEBUG: Ha ocurrido un error. e-mail: Ha ocurrido un error. en STDERR: Ha ocurrido un error.

36

Observese que una implementacin 'pura' de este patrn detendra la cadena. En este ejemplo no ocurre as. Tambin notar que si fuera un implementacin 'pura', habra que cambiar el orden en la creacin del objeto Logger l, pues en este caso, nunca se llegara a lanzar message de la clase StderrLogger, pues tiene un nivel menos importante (mask=5) que su predecesor EMailLogger (mask=3).
import java.util.*; abstract class Logger { public static int ERR = 3; public static int NOTICE = 5; public static int DEBUG = 7; protected int mask; protected Logger next; // el siguiente elemento en la cadena public Logger setNext(Logger l) { next = l; return this; } abstract public void message(String msg, int priority); } //clase class DebugLogger extends Logger{ public DebugLogger(int mask) { this.mask = mask; } public void message(String msg, int priority) { if (priority <= mask) System.out.println("Escribiendo en DEBUG: " + msg); if (next != null) next.message(msg, priority); } } class EMailLogger extends Logger{ public EMailLogger(int mask) { this.mask = mask; } public void message(String msg, int priority) { if (priority <= mask) System.out.println("Enviando un msg); if (next != null) next.message(msg, priority); } } //clase class StderrLogger extends Logger{ public StderrLogger(int mask) { this.mask = mask; } public void message(String msg, int priority) { if (priority <= mask) System.out.println("Escribiendo en STDERR: " + msg); if (next != null) next.message(msg, priority); } } e-mail: " +

37

//Clase class ChainOfResponsibilityExample{ public static void main(String[] args) { // Construimos la cadena // DebugLogger(DEBUG = 7) => EMailLogger(Error = 3) => StderrLogger(Notice = 5) Logger l = new DebugLogger(Logger.DEBUG).setNext( new EMailLogger(Logger.ERR).setNext( new StderrLogger(Logger.NOTICE) ) ); // Ejecutamos l.message("Entrando en function y.", Logger.DEBUG); // manejado por DebugLogger l.message("paso 1 completado.", Logger.NOTICE); // manejado por DebugLogger y StderrLogger l.message("Ha ocurrido un error.", Logger.ERR); // menejado por los tres Logger } }

38