miércoles, 29 de abril de 2015

Command


COMMAND



Propósito

Encapsula una petición como un objeto, lo que permite parametrizar los clientes con distintas peticiones, dejar en cola o registrar solicitudes, y soporta operaciones de deshacer.


También conocido como: Action, Transaction.


Motivación

Este patrón presenta una forma sencilla y versátil de implementar un sistema basado en comandos facilitándose su uso y ampliación, puesto que a veces se quiere poder enviar solicitudes a objetos sin conocer exactamente la operación solicitanda ni del receptor de la solicitud. En general un objeto botón o menú ejecuta solicitudes pero

la solicitud no está implementada dentro del mismo.

La clave de este patrón es una clase abstracta Command que define una operación execute. Son las subclases concretas quienes implementan la operación y especifican el receptor de la orden.


Aplicabilidad

Utilizamos el patrón Command cuando queremos:

  • Parametrizar objetos para llevar a cabo acciones, sobretodo objetos MenuItem. 
  • Especificar, encolar, y ejecutar llamadas en diferentes momentos. Un objeto Comando puede tener una línea de vida independiente de la llamada original. Si el receptor del llamado puede ser representado como una dirección de espacio independiente, luego se puede transferir el objeto Comando para el llamado a un proceso diferente y realizar el llamado ahí. 
  • Soporte deshacer. La operación ejecutarComando( ) puede almacenar estados para revertir efectos en el propio comando. La interfaz debe tener una operación adicional (unExecute) que reversa el efecto de una llamada previa a ejecutar. Los comandos ejecutados están almacenados en una lista de historial. 
  • Soportar cambios en registro en las que se pueden reaplicar en caso de que el sistema colapse. Para agregar operaciones de cargar y guardar en la interfaz comando, se debe mantener un registro permanente de cambios. Recuperarse de un colapso requiere recargar los comandos de registro del disco y reejecutarlos con la operación ejecutar. 
  • Estructurar un sistema alrededor de operaciones de alto nivel construidas sobre operaciones primitivas ya que una estructura es común en los sistemas de información que soportan transacciones. 
Estructura


Participantes

Command: Declara una interfaz para ejecutar una operación

ConcreteCommand: Define una relación entre un objeto Receivor y una acción. Implementa Execute() para invocar la respectiva acción en Receivor.

Client: Crea los objetos ConcreteCommand y su Receiver.

Invoker: Pregunta el comando para llevar a cabo la solicitud.

Receiver: Es la encargada de realizar operaciones asociadas con las peticiones de Execute(). Cualquier clase puede ser Receiver.

Colaboraciones 

  • El cliente crea un objeto ConcreteCommand y especifica su receptor. 
  • Un objeto Invoker guarda el objeto ConcreteCommand. 
  • El Invoker llama a Execute() en Command el cual esta implementado en ConcreteCommand. 
  • El objeto ConcreteCommand llama a las acciones pertinentes sobre su Receiver. 
Consecuencias
  • Command desacopla el objeto que invoca la operación que sabe cómo resolver. 
  • Command es la primera clase de objetos. Puede ser manipulada o extendida como cualquier otro objeto. 
  • Se puede ensamblar Command en un Composite Command (comando Compuesto). 
  • Es fácil adicionar nuevos Commands, porque no se tienen que cambiar las clases existentes. 
Implementación

A la hora de implementar el patrón Command se debe tener en cuenta: 
  • ¿Qué tan inteligente debe ser un comando? Un comando puede tener una amplia gama de habilidades. En un extremo este se limita a definir un compromiso que vincula un receptor y las acciones que llevan a cabo la petición. 
  • Soporte de deshacer y rehacer. Command puede soportar deshacer y rehacer, si se dispone de una opción para revertir su ejecución. Una clase ConcreteCommand puede que necesite construir un estado adicional para haces esto. 
  • Evitar la acumulación de errores en el proceso de deshacer. En la medida en que se hacen y deshacen operaciones es posible que el estado al que se llega diverga del estado original de los objetos. Es necesario que el ConcreteCommand contenga suficiente información para que sea capaz de hacer que los objetos vuelvan al estado original. 
  • En C++ se pueden usar plantillas para representar Commands que no requieren argumentos ni se pueden deshacer 
Usos conocidos 

Las clases Button y MenuItem de Java: 
  • Facilitan la utilización de este patrón. 
  • Declaran los métodos getActionCommand y setActionCommand para dar nombres a las acciones realizadas por los objetos. 
  • Facilitan una correspondencia entre ambos. 

Patrones relacionados
  • Un Composite puede ser usado en la implementación de MacroCommands. 
  • Un Memento puede mantener el estado que requiere Command para deshaces sus efectos. 
  • Un Command que debe ser copiado antes de ser puesto en el historial de una lista actúa como un Prototype. 
Referencias
  • Design Patterns Elements of Reusable Object-Oriented Software, GoF.

Chain of Responsability


Chain of Responsability

Propósito

Establecer una cadena en un sistema, para que un mensaje pueda ser manejado en el nivel en el que se recibe en primer lugar, o ser redirigido a un objeto que pueda manejarlo.


También conocido como: Chain of Responsability (Cadena de Responsabilidad)


Motivación

La petición debe ser procesada por los receptores, lo cual quiere decir que, ésta petición queda al margen del uso exclusivo.

Pretendemos dar una mayor detalle y especificación a las peticiones generadas. Las peticiones serán filtradas por todos los receptores a medida que se van generando los resultados esperados.

Aplicabilidad

El patrón Cadena de Responsabilidad debe usarse cuando: 

  • Hay más de un objeto que puede manejar una petición, y el manejador no se conoce a priori, sino que debería determinarse automáticamente. 
  • Se quiere enviar una petición a un objeto entre varios sin especificar explícitamente el receptor. 
  • El conjunto de objetos que pueden tratar una petición debería ser especificado dinámicamente. 

Estructura





Participantes


Handler (Aprobación): Define una interface para el manejo de las solicitudes.

(optional):  implementa el sucesor de enlaces.

ConcreteHandler (Director, VicePresidente, Presidente): Se ocupa de las solicitudes, es responsable del acceso al sucesor del enlace. Si el ConcreteHandler puede manejar la solicitud, de lo contrario envía la solicitud a un sucesor.

Client (ChainApp): Inicia la solicitud de un objeto ConcreteHandler en la cadena.


Colaboraciones

Cuando un cliente envía una petición, ésta se propaga a través de la cadena hasta que un objeto ManejadorConcreto se hace responsable de procesarla.


Consecuencias


Las ventajas de este patrón son:

  • Reduce el acoplamiento. El patrón libera a un objeto de tener que saber qué otro objeto maneja una petición. Ni el receptor ni el emisor se conocen explícitamente entre ellos, y un objeto de la cadena tampoco tiene que conocer la estructura de ésta. Por lo tanto, simplifica las interconexiones entre objetos. En vez de que los objetos mantengan referencias a todos los posibles receptores, sólo tienen una única referencia a su sucesor. 
  • Añade flexibilidad para asignar responsabilidades a objetos. Se pueden añadir o cambiar responsabilidades entre objetos para tratar una petición modificando la cadena de ejecución en tiempo de ejecución. Esto se puede combinar con la herencia para especializar los manejadores estáticamente. 
Por otra parte presenta el inconveniente de no garantizar la recepción. Dado que las peticiones no tienen un receptor explícito, no hay garantías de que sean manejadas. La petición puede alcanzar el final de la cadena sin haber sido procesada.


Implementacion

Implementación de la cadena sucesora. Hay dos formas posibles de implementarla: 

  • Definir nuevos enlaces (normalmente en el Manejador, pero también podría ser en los objetos ManejadorConcreto). 
  • Usar enlaces existentes (otras asociaciones existentes). Por ejemplo, en el patrón Composición puede existir ya un enlace al padre que puede utilizarse para definir la cadena de responsabilidad sin necesidad de añadir otra asociación. 
  • Conexión de los sucesores. Si no hay referencias preexistentes para definir una cadena, entonces tendremos que introducirlas nosotros mismos. En este caso, el Manejador define la interfaz y además, se encarga de mantener el sucesor. Esto permite que el manejador proporcione una implementación predeterminada de ManejarPetición que reenvíe la petición al sucesor (si hay alguno). Si una subclase de ManejadorConcreto no está interesada en dicha petición, no tiene que redefinir la operación de reenvío. 
  • Representación de peticiones. Hay varias opciones para representar las peticiones: 
  • Una petición es una invocación a una operación insertada en el código. Esto resulta conveniente y seguro, pero sólo se pueden reenviar el conjunto prefijado de peticiones que define la clase Manejador. 
  • Una única función manejadora que reciba un código de petición como parámetro. Esto permite un número arbitrario de peticiones pero emisor y receptor deben ponerse de acuerdo sobre cómo codificarse la petición. 

Código de ejemplo

El cliente hace una petición y según la elección, se crea o se hace la accion dependiendo la clase que tenga esa responsabilidad.

public abstract class Pinturas { 
/*public static int ERR = 3; 
public static int NOTICE = 5; 
public static int DEBUG = 7; 
*/ protected String color; 
protected Pinturas next; 
// el siguiente elemento en la cadena 
public Pinturas setNext(Pinturas l) 
next = l;
return this; 
abstract public void mensaje(String msg); 
public class PinturaBlanca extends Pinturas{ public PinturaBlanca() 
this.color = "Blanca"; 
//this.mask = mask; 
public void mensaje( String msg ) 
if (color.compareTo(msg) == 0) 
System.out.println("Pintamos de Blanco"); 
}
else 
if (next != null) 
next.mensaje(msg); 
public class PinturaAzul extends Pinturas{ public PinturaAzul() 
this.color = "Azul"; 
//this.mask = mask; 
public void mensaje( String msg ) 
if (color.compareTo(msg) == 0) 
System.out.println("Pintamos de Azul"); 
}
else 
if (next != null) 
next.mensaje(msg); 
public class PinturaAmarilla extends Pinturas{ public PinturaAmarilla() 
{
this.color = "Amarillo"; 
//this.mask = mask; 
public void mensaje( String msg ) 
if (color.compareTo(msg) == 0) 
System.out.println("Pintamos de Amarillo"); 
}
else 
if (next != null) 
next.mensaje(msg); 
public class Cliente { 
public static void main(String[] args) 
// Construimos la cadena Pinturas pint = new PinturaAzul().setNext( new PinturaBlanca().setNext( new PinturaAmarilla() ) );
pint.mensaje("Amarillo"); 
}

Usos conocidos
  • Varias bibliotecas de clases usan este patrón para manejar los eventos de usuario. Aunque usan nombres distintos, la idea es siempre la misma: cuando el usuario hace clic con el ratón o pulsa una tecla, se genera un evento y se pasa a lo largo de la cadena. 
  • El framework de editores gráficos Unidraw define objetos que encapsulan peticiones a los objetos Component y ComponentView. Estos objetos se estructuran jerárquicamente, así pueden reenviar interpretaciones de órdenes a su padre, quien a su vez puede reenviarlas, formando una cadena de responsabilidad. 
  • ET++ usa una cadena de responsabilidad para tratar la actualización de gráficos. Un objeto gráfico llama a una operación cada vez que quiere actualizarse, pero el objeto no sabe lo suficiente sobre su contexto, por lo tanto la operación debe reenviar la petición. 
Patrones relacionados

El patrón Cadena de Responsabilidad se suele aplicar junto con el patrón Composite. En él, los padres de los componentes pueden actuar como sucesores.


Referencias

  • Design Patterns Elements of Reusable Object-Oriented Software, GoF.
  • http://kybele.escet.urjc.es/documentos/SI/Patrones/05_Chain.ppt
  • http://dmi.uib.es/~yuhua/APOO07-08/Presentation/ChRespons.pdf

Proxy

PROXY



Propósito

Es un sustituto de otro objeto, para controlar el acceso a él.


También conocido como: Virtual proxy/Surrogate/Sistituto/Apoderado.


Motivación

Una de las razones para controlar el acceso a un objeto, es aplazar el coste total de su creación e inicialización hasta que realmente se necesita para usarlo, de modo que el patrón obliga a que las llamadas a métodos de un objeto ocurran indirectamente a través de un objeto Proxy..


Aplicabilidad

Un proxy remoto proporciona un representante local de un objeto remoto. Un proxy virtual crea objetos costosos sólo cuando es necesario. Un proxy de protección controla el acceso al objeto original. Una referencia inteligente es un sustituto de un simple puntero que realiza alguna acción adicional:Contar el número de referencias al objeto original. Cargar un objeto persistente en memoria cuando es referenciado por vez primera. Bloquea el acceso al objeto real para que no sea modificado por otro objeto.


Estructura




Participantes

Proxy: Tiene referencia al objeto RealSubject, tiene una interfaz idéntica a la de Subject así un proxy puede sustituirse por una RealSubject, y controla el acceso al RealSubject y puede ser el responsable de su creación y borrado.
Subject: Define una interfaz común para RealSubject y Proxy.
RealSubject: Define el objeto real que Proxy representa.
Client: Quien desea acceder al objeto.


Colaboraciones

Client accede a Subject a través de Proxy.


Consecuencias

  • El patrón proxy no es útil en su forma pura, debe ser combinado con un gestor de servicios para satisfacer algún comportamiento de utilidad.
  • El proxy remoto oculta espacios de direcciones diferentes.
  • El proxy virtual evita consumir recursos hasta que no es necesario.
  • El proxy de protección y las referencias inteligentes permiten realizar tareas internas (recolección de basura, controlar accesos, etc.)
  • Permite el copy-on-write: un objeto costoso es compartido hasta que alguien cambia su estado. Suele utilizarse junto con una cuenta de referencias por parte del objeto compartido. Cuando no es referenciado por nadie se autodestruye.
Implementación

El siguiente ejemplo permite modificar un archivo existe y visializarlo doblemente, en la parte izquierda se muestra el archivo real , no editable, y el la parte el archivo editable, cuando se elije guardar cambios, se actualiza el archivo real, sólo hasta ese momento, pues proxy retrasa la creacion y modificación de los objetos, hasta que sea necesario. Debes crear un archivo "Texto" en blog de notas, para que funcione el archivo, al cual le adicionaras la informacion que quieras.


Codigo de ejemplo

package logicap;

/**
*
* @author paola
*/
public interface Archivo {

public String cadenaTexto();
}
package logicap;

import java.io.*;

/**
*
* @author paola
*/
public class ArchivOriginal implements Archivo {

private String contenido = "";

private String temp = "";

public ArchivOriginal() {

this.cargarArchivo();

}

public void cargarArchivo() {

contenido = "";

temp = "";

try {

FileReader Fichero = new FileReader("Texto.txt");

BufferedReader leer = new BufferedReader(Fichero);

while ((temp = leer.readLine()) != null) {

contenido = contenido + temp + "\n";

}

leer.close();

} catch (IOException ioe) {

System.out.println(ioe);

}

}

public String cadenaTexto() {

this.cargarArchivo();

return contenido;

}

}

package logicap;

import java.io.*;
import javax.swing.JOptionPane;

/**
*
* @author Katherin
*/
public class ArchivoProxy implements Archivo {

private ArchivOriginal archivo;

public void guargarArchivo(String str) {
try {
FileWriter fw = new FileWriter("Texto.txt");
fw.write(str, 0, str.length());
fw.close();
} catch (IOException e) {
JOptionPane.showMessageDialog(null, "Se supone que nada podría salir mal.");
}
}

public String cadenaTexto() {
if (archivo == null) {
archivo = new ArchivOriginal();
}
return archivo.cadenaTexto();
}
}

package logicap;

import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.*;

/**
*
* @author paola
*/
public class Pizarra extends JFrame implements ActionListener {

private JTextArea tablero;
private JTextArea tableroProxy;
private ArchivoProxy proxy;
private String texto = "";
private JButton cargarArchivo;
private JButton guardarArchivo;
private JButton refrescar;
private JButton salir;
private Font f;

public Pizarra() {
this.setLayout(null);
this.setTitle("Laboratorio de Moléculas");
this.setSize(800, 500);
this.setLocation(100, 100);

f = new Font("Helvetica", Font.ITALIC + Font.BOLD, 10);
tablero = new JTextArea();
tablero.setSize(350, 300);
tablero.setLocation(10, 10);
tablero.setFont(f);
tablero.setText("");
tablero.setEditable(false);
add(tablero);

JScrollPane areaScrollPane = new JScrollPane(tablero);
areaScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
areaScrollPane.setSize(350, 300);
areaScrollPane.setLocation(10, 10);
this.getContentPane().add(areaScrollPane);

tableroProxy = new JTextArea();
tableroProxy.setSize(350, 300);
tableroProxy.setLocation(400, 10);
tableroProxy.setFont(f);
tableroProxy.setText("");
tableroProxy.setEditable(true);
add(tableroProxy);

JScrollPane areaScrollPane2 = new JScrollPane(tableroProxy);
areaScrollPane2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
areaScrollPane2.setSize(350, 300);
areaScrollPane2.setLocation(400, 10);
this.getContentPane().add(areaScrollPane2);

cargarArchivo = new JButton();
cargarArchivo.setSize(300, 20);
cargarArchivo.setLocation(40, 360);
cargarArchivo.setText("Cargar Archivo");
cargarArchivo.addActionListener(this);
add(cargarArchivo);

guardarArchivo = new JButton();
guardarArchivo.setSize(300, 20);
guardarArchivo.setLocation(40, 390);
guardarArchivo.setText("Guardar Cambios");
guardarArchivo.addActionListener(this);
add(guardarArchivo);

refrescar = new JButton();
refrescar.setSize(300, 20);
refrescar.setLocation(40, 420);
refrescar.setText("Actualizar");
refrescar.addActionListener(this);
add(refrescar);

salir = new JButton();
salir.setSize(100, 50);
salir.setLocation(400, 370);
salir.setText("Salir");
salir.addActionListener(this);
add(salir);

addWindowListener(new Cierre());
}
public void actionPerformed(ActionEvent e) {

if (e.getSource() == cargarArchivo) {
proxy = new ArchivoProxy();
tablero.setText(proxy.cadenaTexto());
tableroProxy.setText(proxy.cadenaTexto());
}
if (e.getSource() == guardarArchivo) {
texto = tableroProxy.getText();
proxy.guargarArchivo(texto);
}
if (e.getSource() == refrescar) {
tablero.setText(proxy.cadenaTexto());
}
if (e.getSource() == salir) {
System.exit(0);
}
}

class Cierre extends WindowAdapter {

@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
}

package improxy;

import logicap.Pizarra;

/**
*
* @author paola
*/
public class Main {

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Pizarra lab=new Pizarra();
lab.setVisible(true);
}

}


Usos conocidos

NEXTSTEP [Add94] utiliza los poderes (los casos de clase NXProxy) como local representantes de los objetos que puedan ser distribuidos. Un servidor proxy crea mando a distancia para los objetos cuando los clientes lo soliciten. Al recibir un mensaje, el proxy codifica junto con sus argumentos y, a continuación, envía el mensaje codificado al objeto remoto. Del mismo modo, el sujeto codifica toda vuelta los resultados y los envía al volver a la NXProxy objeto. 
McCullough [McC87] discute el uso de proxies en Smalltalk para acceder a objetos remotos. Pascoe [Pas86] se describe cómo proporcionar a los efectos secundarios sobre el método de las llamadas y el acceso de control con "Encapsulators".


Patrones relacionados

  • Adapter: un adaptador proporciona una interfaz para el objeto que se adapta. En cambio, una aproximación proporciona la misma interfaz que su tema. Sin embargo, un representante utilizados para protección de acceso podría negarse a realizar una operación que el tema llevará a cabo, por lo que su interfaz puede ser efectivamente un subconjunto de la del sujeto. 
  • Decorator: Aunque los decoradores pueden tener aplicaciones similares como apoderados, decoradores tienen un propósito diferente. Un decorador añade una o más funciones a un objeto, mientras que un servidor proxy controla el acceso a un objeto. Proxy varía en el grado en que su aplicación como un decorador. Una protección proxy podría aplicarse exactamente como un decorador. Por otra parte, un mando a distancia de proxy no contienen una referencia directa a su verdadero tema, pero sólo una referencia indirecta, como "host ID y dirección local de acogida." Un espacio virtual proxy comenzará con una referencia indirecta, tales como un nombre de archivo, sino que eventualmente obtener y utilizar una referencia directa.
Referencias

  • PDF-Departamento de Sistemas Informáticos y Programación Curso de doctorado 1999 - 2000 Patrones de diseño orientado a objetos. 
  • DesIgn Patterns: Elements of Reusable Object-Oriented Software Gamma, Helm, Johnson, Vlissides Editorial Addison-Wesley.
  • kybele.escet.urjc.es/documentos/SI/Patrones/18_Proxy.ppt

Flyweight

FLYWEIGHT

Propósito

Compartir estados para soportar un gran número de objetos pequeños aumentando la eficiencia en espacio.


Motivación

Describe cómo almacenar un gran número de objetos sin un gran coste, para conseguir esto se utilizan objetos que almacenan los estados compartidos y que pueden ser usados por varios objetos simultáneamente.


Aplicabilidad

Cuando se cumplan las siguientes características:

Se utiliza un gran número de objetos.
El coste de almacenamiento es alto debido a la cantidad de objetos.
La mayoría de los estados de los objetos pueden ser creados como comunes.
Muchos objetos pueden ser reemplazados por unos pocos una vez que han sido borrados los estados no comunes.
La mayor parte del estado del objeto puede ser extrínseco.

Estructura


Participantes

Flyweight: Declaran una interface a través de la que flyweights pueden recibir y actuar sobre estados no compartidos.
ConcreteFlyweight: Implementa la interfaz Flyweight y almacena los estados compartidos, si los hay. Un objeto ConcreteFlyweight debe ser compartible. Cualquier estado que almacene debe ser intrínseco; es decir, debe ser independiente de su contexto.
UnsharedConcreteFlyweight: No todas las subclases de Flyweight tienen por qué ser compartidas. La interfaz Flyweight permite que se comparta; no lo fuerza. Es común que los objetos de esta clase tengan hijos de la clase ConcreteFlyweight en algún nivel de su estructura.
FlyweightFactory: Crea y gestiona los objetos flyweight; garantiza que los objetos flyweight se comparten de forma apropiada. Cuando un cliente solicita un flyweight, el objeto de la clase FlyweightFactory proporciona una instancia existente, o crea una.
Client:Contiene referencias a los flyweights, calculando o almacenando los estados no compartidos de los flyweights.

Colaboraciones

Los clientes no crean directamente los objetos Flyweight, sino que debeninvocar las fábricas. El estado extrínseco es mantenido por el cliente ypasado cuando se invocan métodos que lo requieren.

Consecuencias

Ventajas

Produce ahorro de la capacidad almacenamiento
Reduce el número total de objetos
Reduce en gran cantidad el peso de los datos en un servidor.

Desventajas:

Consume un poco mas de tiempo para realizar las busquedas.

Implementación

Considere los siguientes aspectos cuando implemente el patrón de diseño flyweight: 

  • Eliminar estados extrínsecos. El patrón depende ampliamente de identificar es-tados extrínsecos y removerlos de los objetos compartidos. Los estados extrín-secos, por su parte deben ser calcula-dos, en alguna parte donde los requeri-mientos de memoria sean bajos. 
  • Debido a que los flyweight son comparti-dos, no deberían ser instanciados direc-tamente por los clientes. La clase Fly-weightFactory deja a los clientes localizar un flyweight en particular. 
Código de ejemplo

El código ejemplo pinta 5 pelotas en la pantalla, pero solo utiliza un objeto que sirve de referencia a las 5 pelotas.

//Interfa Flyweight

import java.awt.Image;

public interface Pelota {

public Image getPelota();

}

//ConcreteFlyweight implementa la inerfaz y guarda estados intrínsecos

import java.awt.Image;

import java.awt.image.BufferedImage;

import java.io.IOException;

import javax.imageio.ImageIO;

public class PelotaConcreta implements Pelota {


private BufferedImage imagen;

public PelotaConcreta() {

try{

imagen= ImageIO.read(getClass().getClassLoader().getResource("pelota.gif"));

}catch(IOException e){

System.out.println("no se puede cargra la imagen");

}

}

public Image getPelota(){

System.out.println("aqui");

return (Image)imagen;

}

}

//(FlyweightFactory) garantiza que los objetos se inicialicen correctamente.

//Fijese que esta clase es un singleton.

public class PelotaFactory {


private static Pelota miPelota =null;

public static Pelota getPelota(){

if(miPelota==null)miPelota=new PelotaConcreta();

return miPelota;

}

}

//(Client) Mantiene una referencia a pelota

//almacen estados esxtrínsecos.

import java.awt.Image;


public class DibujaPelota {

private Pelota pelota = PelotaFactory.getPelota();

//Estados extrínsicos que son mantenidos por el cliente

private int cordX=0;

private int cordY=0;


public Image getPelota(){

return pelota.getPelota();

}

public void setCordX(int x){

cordX=x;

}

public void setCordY(int y){

cordY=y;

}

public int getCordX(){

return cordX;

}

public int getCordY(){

return cordY;

}

}

//clase que se encarga d la presentacion

import javax.swing.JPanel;

import javax.swing.JButton;

import javax.swing.JFrame;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.awt.Image;

import java.awt.Graphics;

import java.util.Random;


public class Presentacion extends JFrame implementsActionListener{

private final int DIMENSION_IMAGEN =40;

private JPanel panel;

private JButton mover;

private Image imagen=null;

private DibujaPelota pelotas[]={newDibujaPelota(),new DibujaPelota(),newDibujaPelota(),new DibujaPelota(),new DibujaPelota()};

private DibujaPelota pelota=pelotas[0];

private int x=0;

private int y=0;

private Random aleatorio= new Random(1000L);


public Presentacion(){

panel = new JPanel();

mover=new JButton("Mover");

this.setTitle("Pelotas");

this.setSize(350,400);

this.setResizable(false);

this.setVisible(true);

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

panel=(JPanel)this.getContentPane();

panel.setLayout(null);

panel.add(mover);

mover.setBounds(20, 20, 70, 20);

mover.addActionListener(this);

//aleatorio.setSeed(1000);

}

public static void main(String args[]){

new Presentacion();

}

public void paint(Graphics g){

g.fill3DRect(100, 100, 20, 20, true);

g.clearRect(x,y+100,DIMENSION_IMAGEN,DIMENSION_IMAGEN);

imagen=pelota.getPelota();

g.drawImage(imagen,pelota.getCordX(),pelota.getCordY(),DIMENSION_IMAGEN,DIMENSION_IMAGEN,this);

}

public void actionPerformed(ActionEvent e) {

for(int i=0; i<5;>

x=pelotas[i].getCordX();

y=pelotas[i].getCordY();

pelotas[i].setCordX((int)aleatorio.nextLong()*240);

pelotas[i].setCordY((int)aleatorio.nextLong()*340);

pelota=pelotas[i];

}

repaint();

}
}


Usos conocidos

ET + + [WGM88] utiliza para apoyar flyweights look-and-feel , norma afecta a la disposición de elementos de interfaz de usuario (por ejemplo, desplazarse barras, botones, menús, conocidas colectivamente como "widgets") y su decoración (por ejemplo, sombras, biselado). Un widget todos los delegados de su configuración y el comportamiento de dibujo Diseño de un objeto. Cambiar el diseño de objetos cambia el aspecto y, incluso en tiempo de ejecución.


Patrones relacionados

Es a menudo combinado con el patrón composite al aplicar una estructura jerárquica, lógicamente, en términos de un gráfico acíclico dirigido - compartida con la hoja de nodos. A menudo es mejor para la aplicación de state y strategy como objetos flyweights . 


Referencias

  • PDF-Departamento de Sistemas Informáticos y Programación Curso de doctorado 1999 - 2000 Patrones de diseño orientado a objetos.
  • DesIgn Patterns: Elements of Reusable Object-Oriented Software Gamma, Helm, Johnson, Vlissides Editorial Addison-Wesley.
  • www.ldc.usb.ve/~mgoncalves/IS2/sd07/grupo5.ppt 
 


Facade

Facade

Propósito

Proporcionar una interfaz de alto nivel, unificada a un conjunto de interfaces en un subsistema, haciendo más fácil de usar todas aquellas, minimizando las comunicaciones y dependencias entre el liente y los subsistemas.

También conocido como: Facade.

Motivación

Estructurar un sistema en subsistemas ayudando a reducir la complejidad, estructurando un entorno de programación. 

Aplicabilidad

Proporciona una interfaz sencilla a un subsistema complejo, – a medida que un subsistema evoluciona va teniendo más clases, más pequeñas, más flexibles y configurables, – existen clientes que no necesitan tanta flexibilidad y que quieren una visión más simple del subsistema ,– sólo los clientes que necesiten detalles de más bajo nivel accederán a las clases detrás de la fachada, puesto que cuando hay muchas dependencias entre los clientes y las clases de implementación de una abstracción es cuando la fachada desacopla el subsistema de los clientes y de otros subsistemas, mejorando la independencia de subsistemas y la portabilidad.

Para estructurar un sistema en capas –la fachada define el punto de entrada de cada nivel, – se pueden simplificar las dependencias obligando a los subsistemas a comunicarse únicamente a través de sus fachadas.


Estructura




Participantes

Facade: Conoce qué clases son responsables de las peticiones y así, delega las peticiones a los objetos apropiados.
Subsystem: Implementa la funcionalidad del subsistema, realiza el trabajo solicitado por el objeto Facade y no conoce, ni mantiene referencia alguna del objeto mismo Facade. 

Colaboraciones

Los clientes se comunican con el subsistema haciendo peticiones a la Fachada, que las envía a los objetos del subsistema apropiados (la fachada podría también traducir su interfaz a la de las interfaces del subsistema), de modo que los clientes que usan la fachada no tienen que acceder a los objetos del subsistema directamente.

Usos conocidos

Oculta a los clientes los componentes del subsistema, reduciendo el número de objetos con los que tienen que tratar los clientes.

Disminuye el acoplamiento entre un subsistema y sus clientes, un menor acoplamiento facilita el cambio de los componentes del subsistema sin afectar a sus clientes – 

Las fachadas permiten estructurar el sistema en capas, reduciendo las dependencias de compilación# No evita que las aplicaciones puedan usar las clases del subsistema si lo necesitan, eligiendo entre facilidad de uso y generalidad.

El acoplamiento débil permite variar los componentes del subsistema, sin que ello afecte a sus clientes.

La reducción de las dependencias de compilación es de vital importancia en los grandes sistemas de software. 

Una fachada también puede simplificar los sistemas de portar a otras plataformas, ya que es menos probable que la construcción de un subsistema requiere de la construcción todos los demás.


Implementación

package logica;

public class Fachada {

public String activarAire()

{

AireAcondicionadoCarro aire = new AireAcondicionadoCarro();

aire.activarAire();

return aire.getEstadoAlarma();

}

public String activarLuces()

{

LucesCarro luces = new LucesCarro();

luces.encenderLuces();

return luces.getEstadoLuces();

}

public String activarAlarma()

{

AlarmaCarro alarma = new AlarmaCarro();

alarma.activarAlarma();

return alarma.getEstadoAlarma();

}

}

package logica;

public class AlarmaCarro {

private String estadoAlarma;
public void activarAlarma()
{
estadoAlarma= "Se ha activado la alarma";
}
public void desactivarAlarma()
{
estadoAlarma = "Se ha desactivado la alarma";
}
public String getEstadoAlarma()
{
return estadoAlarma;
}

package logica;
public class AireAcondicionadoCarro {

private String estadoAire;

public void activarAire()
{
estadoAire = "Aire acondicionado encendido";
}

public String getEstadoAlarma()
{
return estadoAire;
}
}

package logica;

public class LucesCarro
{
private String estadoLuces;
public void encenderLuces()
{ estadoLuces = "Se han encendido las luces";
}
public String getEstadoLuces()
{
return estadoLuces;
}
}

package interfaz;
import logica.Fachada;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;

public class Conductor extends JFrame implements ActionListener{

private Fachada facha;
private Conductor conduc;
private JButton encenderAire;
private JButton activarAlarma;
private JTextArea txtArea;

public Conductor(){
this.setSize(400,500);
this.setLayout(null);
this.setDefaultCloseOperation(Conductor.DISPOSE_ON_CLOSE);
this.setTitle(":::Carro:::");

txtArea = new JTextArea();
txtArea.setSize(350, 250);
txtArea.setLocation(10, 10);
txtArea.setText("");
txtArea.setEditable(false);
add(txtArea);

encenderAire = new JButton();
encenderAire.setSize(150, 50);
encenderAire.setLocation(50, 300);
encenderAire.setText("Aire Acondicionado Encendido");
this.getContentPane().add(encenderAire);
encenderAire.addActionListener(this);

activarAlarma = new JButton();
activarAlarma.setSize(150, 50);
activarAlarma.setLocation(50, 350);
activarAlarma.setText("Alarma Encendida");
this.getContentPane().add(activarAlarma);
activarAlarma.addActionListener(this);

addWindowListener(new Cierre());

facha = new Fachada();
}
public void actionPerformed(ActionEvent e) {

if (e.getSource() == encenderAire) {
txtArea.setText(facha.activarAire());
}
if (e.getSource() == activarAlarma)
{
txtArea.setText(facha.activarAlarma());
}
}
class Cierre extends WindowAdapter {

@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
}

package interfaz;

/**
*
* @author paola
*/
public class Main {
public static void main(String[] args) {
Conductor ventana=new Conductor();
ventana.setVisible(true);
}


Usos conocidos

ObjectWorks \ Smalltalk compilador sistema. ET en el marco de aplicación + + [WGM88], puede tener una aplicación incorporada en herramientas de navegación para la inspección de sus objetos en tiempo de ejecución. Estas son herramientas de navegación aplicado en un subsistema que incluye una clase llamada Fachada "ProgrammingEnvironment". Esta fachada se define como operaciones InspectObject y InspectClass para acceder a los navegadores.

Las opciones del sistema operativo [CIRM93] utiliza para componer muchas fachadas marcos en uno. Las principales opciones son abstracciones en procesos, almacenamiento, y la dirección espacios. Para cada una de estas abstracciones hay un subsistema correspondiente, aplicarse como un marco, que apoya a las opciones de portar una gran variedad de plataformas de hardware. Dos de estos subsistemas tienen un "representante" (es decir, la fachada). Estos representantes son FileSystemInterface (almacenamiento) y de dominio (dirección espacios).


Patrones relacionados

Normalmente sólo hace falta un objeto Fachada, por lo cual suele implementarse como Singleton. 
Abstract Factory se puede utilizar con Fachada para proporcionar una interfaz para la creación de subsistema de objetos en un subsistema de manera independiente. Resumen de fábrica también se puede utilizarse como una alternativa a la fachada para ocultar las clases específicas de la plataforma.
Mediator es similar a la fachada en el sentido de que la funcionalidad de los resúmenes clases. Sin embargo, el propósito del Mediador es arbitraria resumen de comunicación entre colega objetos, a menudo la centralización de la funcionalidad que no pertenece en cualquiera de ellos. Un mediador de colegas y son conscientes de comunicarse con el mediador en lugar de comunicarse unos con otros directamente. En contraste, un fachada simplemente resúmenes de la interfaz con el subsistema de objetos para que sean más fáciles a utilizar, pero no definir nuevas funciones, y las clases del subsistema no sabe sobre él.

Referencias

PDF-Departamento de Sistemas Informáticos y Programación Curso de doctorado 1999 - 2000 Patrones de diseño orientado a objetos.
DesIgn Patterns: Elements of Reusable Object-Oriented Software Gamma, Helm, Johnson, Vlissides Editorial Addison-Wesley.