viernes, 29 de mayo de 2009

VALIDADOR

Este es un proyecto que se realizo aplicando los patrones prototipe y singleton
haciendo una conexion a base de datos para la validación de usuarios a un sistema.

package co.edu.udistrital.validador.bd;

import java.sql.*;

/**
* Clase encargada de realizar la conexion con la base de datos esta misma clase se encarga de consultar y hacer persistencia de datos.
*/
public class Conexion {

static private String bd = "validador";
static private String login = "usuario2";
static private String password = "1234";
static private String url = "jdbc:mysql://localhost/" + bd;
static private Conexion conex = null;
private String CadenaSql;
private Connection conexion = null;

/**
* el contructor se encargada de realizar la conexion a la base de datos
* y muestra en consola mensajes si se pudo o no conectar a labase de datos.
*/
private Conexion() {
try {
System.out.println("Tratando de cargar el driver");
Class.forName("com.mysql.jdbc.Driver");
conexion = DriverManager.getConnection(url, login, password);
if (conexion != null) {
System.out.println("Conexion a base de datos " + bd + " OK");
}
} catch (SQLException sqlEx) {
System.out.println(sqlEx);
} catch (ClassNotFoundException ex) {
System.out.println(ex);
}
}

public String EjecutarSql() {
try {
Statement stmt = conexion.createStatement();
stmt.executeUpdate(CadenaSql);

} catch (SQLException ex) {

System.out.println("Totio");
}
return ("Fue un exito");
}

/**
*
* Funcion encargada de realizar las consultas para poder usarla debe existir
* una conexion a base de datos
*
*
* @return ResultSet
*/
public ResultSet Consultar() {
ResultSet tabla = null;
try {
Statement stmt = conexion.createStatement();
tabla = stmt.executeQuery(CadenaSql);
} catch (SQLException ex) {
System.out.println(ex);
}
return tabla;
}

/**
* Setter que asigna el valor a la cadenaSql
*
* @param String cadena;
*/
public void setCadena(String cadena) {
CadenaSql = cadena;
}

/**
* getter que retorna
*
* @return Connection;
*/
public Connection getConectar() {
return conexion;
}

/**
* Funcion encargada de realizar la desconexion a base de datos
*/
public void desconectar() {
conexion = null;
}

/**
* Funcion encargada de retornar el objeto conexion y garantiza que la clase se instancie una sola vez.
* @return Conexion
* @uml.property name="conexion"
*/
static public Conexion getConexion() {
if (conex == null) {
conex = new Conexion();
}
return conex;
}
}

package co.edu.udistrital.validador.Logica;

/**
* Clase que implementa la interface Cloneable
*/
public abstract class Usuario implements Cloneable {

private String tipoDeUsuario = "NaDa";
private boolean obtenerUsuarios = false;
private boolean entrarSistema = false;
private boolean eliminarUsuario = false;
private boolean modificarUsuario = false;
private boolean adicionarUsuario = false;
private String nombre;
private String identificacion;
private String apellido;

/**
* metodo que recibe el nombre del tipo de Usuario
* @param String
* @uml.property name="tipoDeUsuario"
*/
public void setTipoDeUsuario(String usuario) {
this.tipoDeUsuario = usuario;

}


/**
* metodo que recibe el valor boolena de entrarsistema
* @param boolean
* @uml.property name="entarSistema"
*/
public void setEntrarSistema(boolean b) {
this.entrarSistema = b;
}

/**
* metodo que recibe el valor boolena de obtenerUsuarios
* @param boolean
* @uml.property name="obtenerUsuarios"
*/
public void setObtenerUsuario(boolean b) {
this.obtenerUsuarios = b;
}

/**
* metodo que recibe el valor boolean de EliminarUsuario
* @param boolean
* @uml.property name="eliminarUsuario"
*/
public void setEliminarUsuario(boolean b) {
this.eliminarUsuario = b;

}
/**
* metodo que recibe el valor boolean de EliminarUsuario
* @param boolean
* @uml.property name="eliminarUsuario"
*/
public void setModifiarUsuario(boolean b) {
this.modificarUsuario = b;


}
/**
* metodo que recibe el valor boolean de EliminarUsuario
* @param boolean
* @uml.property name="eliminarUsuario"
*/
public void setAdicionarUsuario(boolean b) {
this.adicionarUsuario = b;

}
public void setIdentificacion(String identificacion) {
this.identificacion = identificacion;
}

public void setNombre(String nombre) {

this.nombre = nombre;
}

public void setapellido(String apellido) {
this.apellido = apellido;
}
public boolean getEliminarUsuario(){
return this.eliminarUsuario;
}
public boolean getObtenerUsuario(){
return this.obtenerUsuarios;
}
public boolean getModifiarUsuario(){
return this.modificarUsuario;
}
public String getTipoDeUsuario() {
return this.tipoDeUsuario;
}
public boolean getAdicionarUsuario(){
return this.adicionarUsuario;
}
public String getIdentificacion() {
return identificacion;
}

public String getNombre() {
return nombre;
}

public String getApellido() {
return apellido;
}

public String adicionarUsuario() {
String CadenaSQL;
if (adicionarUsuario) {
CadenaSQL = "INSERT INTO clientes VALUES('" + this.nombre + "','" + this.apellido + "','" + this.identificacion + "')";
return CadenaSQL;
}else{
return CadenaSQL = null;
}
}

public String modificarUsuario() {
String CadenaSQL;
if (modificarUsuario) {
CadenaSQL = "UPDATE clientes SET apellido = '" + this.apellido + "', documento = '" + this.identificacion + "' WHERE (nombre = '" + this.nombre + "')";
return CadenaSQL;
}else{
return CadenaSQL = null;
}

}

public String eliminarUsusario() {
String CadenaSQL;
if (eliminarUsuario) {
CadenaSQL = "DELETE FROM clientes WHERE(nombre = '" + this.nombre + "')";
return CadenaSQL;
}else{
return CadenaSQL = null;
}
}

public String consultarUsuarios() {
String CadenaSQL;
if (obtenerUsuarios) {
CadenaSQL = "SELECT * FROM clientes";
return CadenaSQL;
}else{
return CadenaSQL = null;
}
}

public String consultarUnUsuario() {
String CadenaSQL;
CadenaSQL = "SELECT * FROM clientes WHERE(nombre = '" + this.nombre + "')";
return CadenaSQL;
}

}

package co.edu.udistrital.validador.Logica;
/**
* Clase que define un tipo de usuario, hereda de la clase Usuario
*/

public class TipoUsuarioA extends Usuario{
/**
* Metodo heredado de la clase usuario, que a su vez implementa
* la interface Cloneable
*
* @return Object
*/
public Object clone(){
Object o=null;
try{
o=super.clone();
}catch(CloneNotSupportedException e){
System.out.println("Error en tiempo de clonacion");
}
return o;
}

/**
* Metodo que crea la clonacion y ejecuta la autoclonacion
*
* @return Usuario
*/
public Usuario copiarTipo(){
Usuario a=(Usuario)clone();
a.setTipoDeUsuario("Usuario de Tipo A");
a.setEntrarSistema(true);
a.setObtenerUsuario(true);
a.setEliminarUsuario(true);
a.setAdicionarUsuario(true);
a.setModifiarUsuario(true);
return a;
}

}

package co.edu.udistrital.validador.Logica;

/**
* Clase que define un tipo de usuario, hereda de la clase Usuario
*/
public class TipoUsuarioB extends Usuario {
/**
* Metodo heredado de la clase usuario, que a su vez implementa
* la interface Cloneable
*
* @return Object
*/
public Object clone() {
Object o = null;
try {
o = super.clone();
} catch (CloneNotSupportedException e) {
System.out.println("Error en tiempo de clonacion");
}
return o;
}

/**
* Metodo que crea la clonacion y ejecuta la autoclonacion
*
* @return Usuario
*/
public Usuario copiarTipo() {
Usuario a = (Usuario) clone();
a.setTipoDeUsuario("Usuario de Tipo B");
a.setEntrarSistema(true);
a.setModifiarUsuario(true);
return a;
}
}

package co.edu.udistrital.validador.Logica;

import co.edu.udistrital.validador.bd.Conexion;
import java.sql.*;

/**
* Clase que valida ingreso a los tipos de ususario. Esta clase implementa el patron Singleton ya que solo se necesita una instancia de esta.
*/
public class Validador {

private Conexion conexion;
private int tipoUsuario=0;
private boolean valida;
private String usuario;
private String clave;

/**
* Retorna el numero de clave validada que ingreso el cliente
* @return int
* @uml.property name="tipoUsuario"
*/
public int getTipoUsuario() {
return this.tipoUsuario;
}

public Validador() {
//Crea una instancia de la clase conexion
conexion = Conexion.getConexion();
}

/**
* consulta la tabla usuarios en la base de datos y valida
* segun la clave ingresado por el cliente
*
* @param String
* @return int
*/
public boolean validar(String cla, String usu) {
this.valida = false;
this.clave = cla;
this.usuario=usu;
conexion.setCadena("SELECT * FROM usuarios where login ='"+usuario+"'");
ResultSet tabla = conexion.Consultar();
try {
while (tabla.next()) {
if (this.clave.compareTo(tabla.getString("clave"))==0) {
this.tipoUsuario = Integer.parseInt(tabla.getString("tipo"));
this.valida = true;
}

}
} catch (SQLException ex) {
System.out.println("Problemas con la tabla");
}
return this.valida;
}
}

package co.edu.udistrital.validador.presentacion;

import co.edu.udistrital.validador.Logica.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;


/**
* Clase que se encarga de generar la interfaz gr�fica y de relacionarla co la l�gica
*/

public class Presentacion implements ActionListener {

//atributos de la GUI
private JFrame frame;
private JButton aceptar;
private JButton clear;
private JLabel log;
private JLabel pass;
private JPasswordField txtpassword;
private JTextField txtloging;
private Container pane;

//atributos de validacion y usuarios
private Validador val;
private TipoUsuarioA TipoA;
private TipoUsuarioB TipoB;
private Usuario usuario = null;

/**
* El costructor de la clase inicializa todos los componentes de la GUI
*
*/

public Presentacion() {
frame = new JFrame("Validador");
aceptar = new JButton("Aceptar");
clear = new JButton("Cls");
log= new JLabel("Usuario: ");
pass= new JLabel("Password: ");
txtpassword = new JPasswordField(0);
txtloging = new JTextField(0);
pane = new JPanel();
val = new Validador();

TipoA = new TipoUsuarioA();
TipoB = new TipoUsuarioB();

pane = frame.getContentPane();
pane.setLayout(null);

log.setBounds(30, 20, 100, 20);
pass.setBounds(30, 60, 100, 20);
txtloging.setBounds(130, 20 , 200, 25);
txtpassword.setBounds(130, 60, 200, 25);
aceptar.setBounds(240, 120, 90, 30);
clear.setBounds(30, 120, 90, 30);
aceptar.addActionListener(this);
clear.addActionListener(this);

frame.add(clear);
frame.add(aceptar);
frame.add(log);
frame.add(pass);
frame.add(txtpassword);
frame.add(txtloging);
frame.pack();

frame.setBounds(450, 450, 380, 200);
frame.setResizable(false);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

/**
* Este m�todo se encarga de inicializar el usuario adecuaado de acuerdo con la validaci�n
* @param t - tipo de usuario(dato que se optiene en la validaci�n)
* @return Usuario que ingresa al sistema.
*/

public Usuario mostrarTipo(int t) {
switch (t) {
default:

case 1:
usuario = TipoA.copiarTipo();
break;

case 2:
usuario = TipoB.copiarTipo();
break;
}

return usuario;
}

/**
* M�todo principal del programa
* @param args
*/

public static void main(String[] args) {
new Presentacion();
}

/**
* M�todo de la interface ActionListener, que se implementa, para manejar
* los eventos generados por los botones que hacen parte del programa.
*/

public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(this.aceptar)) {

/*
* Despues de oprimir el boton aceptar se corre esta lineas de codigo.
* Aqu� se llama el meto validar de validaci�n para validar el tipo de usuario.
* Si el usuario existe en el sistema el m�todo validar devuelve true.
* Luego con los dato otrogados por la clase validador se muestra un mensaje con el tipo de usuario.
*/

if (val.validar(this.txtpassword.getText(),this.txtloging.getText())) {
new ModuloPrincipal(this.mostrarTipo(val.getTipoUsuario()));
} else {
JOptionPane.showMessageDialog(null, "USUARIO NO EXISTE", "ERROR", JOptionPane.ERROR_MESSAGE);

}
}
if (e.getSource().equals(this.clear)) {
this.txtpassword.setText("");
}
}
}

package co.edu.udistrital.validador.presentacion;

import co.edu.udistrital.validador.Logica.*;
import co.edu.udistrital.validador.bd.*;
import java.awt.event.ActionEvent;

import javax.swing.*;

import java.awt.*;
import java.awt.event.*;
import java.sql.SQLException;
import java.util.StringTokenizer;


import javax.swing.table.DefaultTableModel;
/**
* clase que se encarga de generar la interfaz gráfica para los usarios registrados.
* @author Priscilos
*/

public class ModuloPrincipal implements ActionListener {

Conexion conexion;
Usuario usuario;
//Usuario usu;
JFrame frame;
JPanel pane;
Container panelTabla;
JTabbedPane pestana;
JSplitPane separaPaneles;
JMenuBar barra;
JMenu menu;
JMenuItem lisPiezasDis;
JMenuItem listClientes;
JMenuItem listapiezas;
JButton btnGuardar, btnModificar, btnConsultar, btnEliminar, btnConsultarLista, btnBorrar;
JLabel lblDatosClientes, lblNombre, lblApellido, lblIdentificacion;
JTextField txtNombre, txtApellido, txtIdentificacion;
DefaultTableModel modeloTabla;
JTable tablaConsultas, tablaPiezas;
JScrollPane scrollPanel;
StringTokenizer token;
StringTokenizer tokens;
int numTab;
int nDatos;
double[] entrega;
double[] reserva;
char administrador;
java.sql.ResultSet tabla;

/**
* El constructor de la clase inicializa todos los componentes de la GUI
* que pueden variar de acuerdo con el tipo de usario que ingreas.
* @param usu - usuario que ingreas al interfaz gráfica.
*/

public ModuloPrincipal(Usuario usu) {
conexion = Conexion.getConexion();
usuario = usu;
frame = new JFrame("...:::" + usuario.getTipoDeUsuario() + ":::...");
pane = new JPanel(null);
panelTabla = new JPanel();

panelTabla.setLayout(null);

pestana = new JTabbedPane();

btnGuardar = new JButton("Guardar");
btnModificar = new JButton("Editar");
btnConsultar = new JButton("Consultar");
btnEliminar = new JButton("Eliminar");
btnConsultarLista = new JButton("Registrados");

btnBorrar = new JButton("Borrar");






lblDatosClientes = new JLabel("Datos del Usuario");
lblNombre = new JLabel("Nombre");
lblApellido = new JLabel("Apellido");
lblIdentificacion = new JLabel("Identificacion");


txtNombre = new JTextField(15);
txtApellido = new JTextField(15);
txtIdentificacion = new JTextField(15);


separaPaneles = new JSplitPane();

pestana.add("Listas", panelTabla);



lblDatosClientes.setBounds(20, 30, 160, 20);
lblNombre.setBounds(35, 60, 160, 20);
lblIdentificacion.setBounds(35, 90, 160, 20);
lblApellido.setBounds(35, 120, 160, 20);

txtNombre.setBounds(180, 60, 160, 20);
txtIdentificacion.setBounds(180, 90, 160, 20);
txtApellido.setBounds(180, 120, 160, 20);

btnGuardar.setBounds(30, 460, 85, 30);
btnModificar.setBounds(115, 460, 85, 30);
btnConsultar.setBounds(200, 460, 85, 30);
btnEliminar.setBounds(285, 460, 85, 30);
btnBorrar.setBounds(285, 425, 85, 30);
btnConsultarLista.setBounds(330, 440, 110, 30);


pane.add(lblDatosClientes);
pane.add(lblNombre);
pane.add(lblApellido);
pane.add(lblIdentificacion);

pane.add(txtNombre);
pane.add(txtApellido);
pane.add(txtIdentificacion);

pane.add(btnGuardar);
pane.add(btnModificar);
pane.add(btnConsultar);
pane.add(btnEliminar);

pane.add(btnBorrar);
panelTabla.add(btnConsultarLista);
btnModificar.setEnabled(false);
btnEliminar.setEnabled(false);
btnGuardar.setEnabled(usuario.getAdicionarUsuario());
btnConsultarLista.setEnabled(usuario.getObtenerUsuario());




separaPaneles.setRightComponent(pestana);
separaPaneles.setLeftComponent(pane);
pestana.setMinimumSize(new Dimension(400, 50));
pane.setPreferredSize(new Dimension(410, 110));

btnGuardar.addActionListener(this);
btnModificar.addActionListener(this);
btnConsultar.addActionListener(this);
btnEliminar.addActionListener(this);
btnConsultarLista.addActionListener(this);
btnBorrar.addActionListener(this);



frame.getContentPane().add(separaPaneles, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setSize(900, 550);
frame.setVisible(true);
}

//crea las tablas
public void mostrarTabla(String CadenaSQl, String[] columNom, int k) {
if (numTab >= 1) {
scrollPanel.setVisible(false);
}
Object[][] dato = new Object[100][k];
conexion.setCadena(CadenaSQl);
tabla = conexion.Consultar();

try {
int i = 0;
while (tabla.next()) {
for (int j = 1; j < k; j++) {
dato[i][j - 1] = tabla.getString(j);

}
i++;

}
} catch (SQLException ex) {

ex.printStackTrace();
}


modeloTabla = new DefaultTableModel(dato, columNom);
tablaConsultas = new JTable(modeloTabla);
tablaConsultas.setPreferredScrollableViewportSize(new Dimension(450, 400));
scrollPanel = new JScrollPane(tablaConsultas);
scrollPanel.setBounds(15, 30, 435, 400);
panelTabla.add(scrollPanel);
numTab++;
}

public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(btnGuardar)) {
usuario.setNombre(txtNombre.getText());
usuario.setIdentificacion(txtIdentificacion.getText());
usuario.setapellido(txtApellido.getText());


conexion.setCadena(usuario.adicionarUsuario());
System.out.println(conexion.EjecutarSql());
}
if (e.getSource().equals(btnModificar)) {
usuario.setNombre(txtNombre.getText());
usuario.setIdentificacion(txtIdentificacion.getText());
usuario.setapellido(txtApellido.getText());

conexion.setCadena(usuario.modificarUsuario());
System.out.println(conexion.EjecutarSql());
}
if (e.getSource().equals(btnConsultar)) {

usuario.setNombre(txtNombre.getText());
conexion.setCadena(usuario.consultarUnUsuario());
tabla = conexion.Consultar();
try {
while (tabla.next()) {
txtNombre.setText(tabla.getString(1));
txtApellido.setText(tabla.getString(2));
txtIdentificacion.setText(tabla.getString(3));

}
} catch (SQLException ex) {

ex.printStackTrace();
}
btnModificar.setEnabled(usuario.getModifiarUsuario());
btnEliminar.setEnabled(usuario.getEliminarUsuario());
}
if (e.getSource().equals(btnEliminar)) {
usuario.setNombre(txtNombre.getText());
conexion.setCadena(usuario.eliminarUsusario());
System.out.println(conexion.EjecutarSql());

}
if (e.getSource().equals(btnConsultarLista)) {
String[] columNom = {"Nombre", "apellido", "identificacion"};
mostrarTabla(usuario.consultarUsuarios(), columNom, 4);

}
if(e.getSource().equals(btnBorrar)){
txtNombre.setText("");
txtApellido.setText("");
txtIdentificacion.setText("");
}




}


}

martes, 26 de mayo de 2009

UML

Diagramas de UML

Diagramas de Clase:

Clase
En UML, una clase es representada por un rectángulo que posee tres divisiones:


En la parte superior el nombre de la clase, el segundo recuadro los atributos y el tipo de visibilidad, por ultimo, en le ultimo recuadro estarán los métodos con su tipo de visibilidad

Visibilidad
Los atributos o características y los metodos de una Clase pueden ser de tres tipos, los que definen el grado de comunicación y visibilidad de ellos con el entorno, estos son:
public (+): Indica que el atributo o metodo será visible tanto dentro como fuera de la clase, es decir, es accsesible desde todos lados.
Private (- ): Indica que el atributo o metodo sólo será accesible desde dentro de la clase (sólo sus métodos lo pueden accesar).
protected (#): Indica que el atributo o metodo no será accesible desde fuera de la clase, pero si podrá ser accesado por métodos de la clase además de las subclases que se deriven (ver herencia).

Herencia
Podemos ver la herencia como una generalización de una clase en la cual se
muestra ciertas características especificas a una en la cual se definen una más
generales. La relación de herencia se representa mediante un triángulo en el
extremo de la relación que corresponde a la clase más general o clase “padre”.


Realización
Es una relación semántica entre clasificadores, en donde un clasificador especifica un contrato que otro clasificador garantiza que cumplirá. Se pueden encontrar relaciones de realización: entre interfaces y las clases o componentes que las realizan, y entre los casos de uso y las colaboraciones que los realizan.


Agregación
Representa una relación parte_de entre objetos. El símbolo de
agregación es un diamante colocado en el extremo en el que está la clase
que representa el “todo”.

Composicion
Las composiciones son asociaciones que representan acumulaciones muy fuertes. Esto significa que las composiciones también forman relaciones completas, pero dichas relaciones son tan fuertes que las partes no pueden existir por sí mismas. Únicamente existen como parte del conjunto, y si este es destruido las partes también lo son.
En UML, las composiciones están representadas por un rombo sólido al lado del conjunto.


Diagramas de objetos

Muestran un conjunto de objetos y sus relaciones (una situación concreta en un momento determinado).

Los diagramas de objetos representan instantáneas de instancias de los elementos que aparecen en los diagramas de clases
Un diagrama de objetos expresa la parte estática de una interacción.
Para ver los aspectos dinámicos de la interacción se utilizan los diagramas de interacción (diagramas de secuencia y diagramas de comunicación/colaboración)

Diagramas de interacción

Muestran una interacción concreta: un conjunto de objetos y sus relaciones, junto con los mensajes que se envían entre ellos.

Diagramas de secuencia

Resaltan la ordenación temporal de los mensajes que se intercambian.

Muestran la secuencia de mensajes entre objetos durante un escenario
concreto (paso de mensajes).
- En la parte superior aparecen los objetos que intervienen.
- La dimensión temporal se indica verticalmente (el tiempo transcurre hacia abajo).
- Las líneas verticales indican el período de vida de cada objeto.
- El paso de mensajes se indica con flechas horizontales u oblicuas (cando existe demora entre el envío y la atención del mensaje).
- La realización de una acción se indica con rectángulos sobre las líneas de actividad del objeto que realiza la acción.

Resaltan la organización estructural de los objetos que intercambian mensajes.

Los diagramas de secuencia y de comunicación son isomorfos:
- Un diagrama de secuencia se puede transformar mecánicamente en un diagrama de comunicación.
- Un diagrama de comunicación se puede transformar automáticamente en un diagrama de secuencia.



Diagramas de comunicación/colaboración
La distribución de los objetos en el diagrama permite observar
adecuadamente la interacción de un objeto con respecto de los demás
- La perspectiva estática del sistema viene dada por las relaciones existentes entre los objetos (igual que en un diagrama de objetos).
- La vista dinámica de la interacción viene indicada por el envío de mensajes a través de los enlaces existentes entre los objetos.

Diagramas de casos de uso
(actores y casos de uso del sistema)

Los diagramas de uso se suelen utilizar en el modelado del sistema desde el punto de vista de sus usuarios para representar las acciones que realiza cada tipo de usuario.

Diagramas de estados
(estados y transiciones entre estados),

Los diagramas de estados son especialmente importantes para describir el comportamiento de un sistema reactivo (cuyo comportamiento está dirigido por eventos).

Diagramas de actividades

(flujo de control en el sistema)

Los diagramas de actividades muestran el orden en el que se van realizando tareas dentro de un sistema (el flujo de control de las actividades).

Diagramas de componentes
(componentes y dependencias entre ellos) Organización lógica de la implementación de un sistema

lunes, 25 de mayo de 2009

COMPORTAMIENTO

Chain of Responsability
intencion
establecer una cadena en un sistema, para que un mensaje pueda ser manejado en el que se recibe en primer lugar, o ser redirigido a un objeto que pueda manejarlo.

Motivacion
Considere la posibilidad de una ayuda sensible al contexto para la instalación de una interfaz gráfica de usuario. El usuario puede obtener información de ayuda en cualquier parte de la interfaz sólo haciendo clic en ella. La ayuda que se proporciona por parte depende de la interfaz que es seleccionado y su contexto, por ejemplo, un widget de botón en un cuadro de diálogo puede tener diferentes información de ayuda que un botón similar en la ventana principal. Si no hay ninguna ayuda específica existe información de que parte de la interfaz, el sistema de ayuda debe mostrar un mensaje de ayuda de carácter más general sobre el contexto inmediato-el cuadro de diálogo en su conjunto, por ejemplo. Por lo tanto, es natural de organizar la información de ayuda en función de su generalidad-desde los más específicos de la más general. Además, es claro que una solicitud de ayuda es manejado por un interfaz de usuario de varios objetos, que uno depende del contexto y la forma específica de la ayuda disponible.
El problema aquí es que el objeto que en última instancia, proporciona la ayuda no se conoce explícitamente al objeto (por ejemplo, el botón) que inicia la solicitud de ayuda. Qué necesitamos es una manera de disociar el botón que inicia la solicitud de ayuda de los objetos que puedan proporcionar información de ayuda. El patrón Chain of Responsability define que sucede.
La idea de este patrón es disociar los remitentes y receptores de varios objetos, dando la oportunidad de la tramitación de una solicitud. La petición se transmite a lo largo de una cadena de
objetos hasta que uno de ellos se ocupa de ella.

Estructura

Participantes
Handler
define una interfaz para la tramitación de las solicitudes.

ConcreteHandler
se ocupa de las solicitudes es responsable.
pueden tener acceso a su sucesor.
si el ConcreteHandler puede manejar la solicitud, lo hace de otra que remite la solicitud a su sucesor.
Cliente
inicia la solicitud de ConcreteHandler un objeto en la cadena.

Consecuencias
El patron Chain Responsability ofrece una gran flexibilidad para el procesamiento de eventos de una aplicación , por que maneja la complejidad de la gestión de evento dividiendo las responsabilidades entre elementos mas simples. Esto permite que un conjunto de clases se comporte como una unidad, porque los eventos producidos en una clase pueden ser enviados a otras clases manejador o a traves del objeto compuesto.
Por supuesto, la flexibilidad que proporciona este patrón tiene un precio este patrón es difícil de desarrollar, comprobar y depurar . Conforme el direccionamiento de la cadenas hace mas complejo, hay que controlar si los eventos están siendo enviados correctamente.

Command

Intención
Encapsular un comando en un objeto de tal forma que pueda ser almacenado, pasado a métodos y devuelto igual que cualquier otro objeto.

Motivación
A veces se quiere poder enviar solicitudes a objetos sin conocer exactamente la operación solicitada 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.
Una biblioteca de clases para interfaces de usuario tendrá objetos como botones y elementos
de menú responsables de realizar alguna operación en respuesta a una entrada del usuario.

Estructura

Participantes

Command
Declara la interface para la ejecucion de la operacion

ConcreteCommand
Define la relación entre el objeto Receiver y una acción
Implemeta Execute() al invocar las operaciones correspondientes en Receiver
Client
Crea un objeto ConcreteCommand y lo relaciona con su Receiver
Invoker
Le hace solicitudes al objeto Command
Receiver
Sabe como ejecutar las operaciones asociadas a la solicitud. Cualquier clase puede ser receptora.

Consecuencias

El patron Command ofrrece flexibilidad de distintas formas:
desacopla la fuente o el disparador del evento del objeto que tiene el conocimiento para ejecutar la tarea.
Comparte instancias de Command entre distintos objetos.
Permite reemplazar objetos Command y/o Receriver en tiempo de ejecución.
Hace que los comandos sean objetos normales, teniendo todas las propiedades usuales de los objetos.
Facilita la introducción de nuevos comandos; tan solo escriba otra implementación de la interfaz e introduzca la en la aplicación.


Interpreter
Intencion
Dado un Lenguaje, definir la representación de una gramática y un interpretador, que pueda computar entradas de ese Lenguaje.

Motivación
Usamos las expresiones regulares como un estándar para especificar patrones de cadenas. En lugar de construir algoritmos personalizados para que coincida con patrón contra las cuerdas, algoritmos de búsqueda pueden interpretar una expresión regular que especifica un conjunto de cadenas de igualar.
El patrón de interpretación se describe cómo definir una gramática simple para las lenguas, representan frases en la lengua, e interpretar las sentencias.
Por ejemplo, la siguiente gramática define las expresiones regulares:
Expresión:: = literal | alternancia | secuencia | repetición | '(' expresión ')'
Alternancia:: = expresión '|' expresión
Secuencia:: = expresión 'y' expresión
Repetición:: = expresión '*'
Literal:: = 'a' | 'b' | 'c' | ... ( 'a' | 'b' | 'c' | ... *)
Expresión es el símbolo de inicio y literal es un símbolo terminal de la definición de palabras sencillas.

El intérprete utiliza patrón cinco clases para representar a la gramática: una clase abstracta RegularExpression y sus cuatro subclases LiteralExpression, AlternationExpression, SequenceExpression y RepetitionExpression.

Estructura

Participantes
AbstractExpression
Se declara una operación de resumen Interpretar que es común a todos los nodos del árbol de sintaxis abstracta.
TerminalExpression
Ejecuta una operación Interpretar símbolos asociados con la terminal en la gramática.
Una instancia se requiere para cada símbolo terminal en una frase.
NonterminalExpression
Una de esas clases es necesaria para cada regla R:: = R1 R2 ... Rn en la gramática.
Mantiene el tipo de variables de instancia AbstractExpression para cada uno de los símbolos a través de R1 Rn.
Ejecuta una operación para nonterminal Interpretar símbolos de la gramática. Interpretar normalmente se llama a sí mismo recursivamente sobre las variables que representan a través de R1 Rn.
Contexto
Que contiene información global para el intérprete.
Cliente
Se basa (o se da) una sintaxis abstracta que representa un árbol en el idioma en que se define la gramática. El árbol de sintaxis abstracta se monta a partir de las instancias de la expresión y Terminal NonterminalExpression clases.
Interpretar o invoca la operación.

Consecuencias
Gramáticas Fáciles de cambiar y extender.
Fácil Implementación.
Gramáticas Complejas son difíciles de Mantener.
Agregar nuevas formas de interpretar las cosas es sencillo.

Iterator

Intención
Proporciona una forma coherente de acceder secuencialmente a los elementos de una colección, independientemente del tipo de colección subyacente.

Motivación
Una colección de objetos, tal como una lista deberían proveer una forma o camino de acceso a sus elementos sin exponer su representación interna.
Por otra parte, se podría necesitar también recorrer la lista de diferentes formas, dependiendo del problema al que se le deba dar solución. Pero probablemente no se quiera llenar la “interface Lista” con operaciones que recorran sus elementos en distintas direcciones. También se podría tener más de un recorrido pendiente por recorrer en la misma lista.
El patrón de diseño ITERATOR permite resolver los problemas anteriormente planteados. La idea principal de este patrón es tomar la responsabilidad de acceso y recorrido de los objetos de una lista, agregando a esta última un objeto de tipo Iterator.
La Clase Iterator define una interface que permite acceder a los elementos de una lista. Un Objeto de tipo Iterator es el encargado de ir guardando el recorrido del elemento corriente, es decir, conoce los elementos que ya se han recorrido.


Estructura

Participantes
Iterator
define una interface de acceso y recorrido de los elementos de una lista.
ConcreteIterator
implementa la interface Iterator y mantiene o guarda el recorrido del ítem corriente
Aggregate
define una interface que permite crear objetos de tipo Iterator.
ConcreteAggregate
implementa la interface de creación de objetos Iterator y retorna una instancia apropiada de la clase ConcreteIterator

Consecuencias
Este patrón tiene tres consecuencias importantes:
Soporta variaciones en el recorrido de una colección, puesto que estructuras complejas pueden requerir recorridos en muchas formas. Los iteradores hacen fácil cambiar el algoritmo de recorrido, con sólo reemplazar la instancia del iterador a una diferente.
Los iteradores simplifican la interfaz de las colecciones, ya que la interfaz de los recorridos se encuentra en los iteradores y no en la clase que corresponde a la estructura en cuestión.
Más de un recorrido puede estar pendiente en una colección, puesto que cada iterador mantiene la pista de su recorrido. Por lo tanto, se puede tener más de un recorrido en progreso al mismo tiempo.

Mediator
Intención
Simplificar la comunicación entre los objetos de un sistema introduciendo un único objeto que gestiona la distribución de mensajes entre los otros.

Motivación
Cuando muchos objetos interactúan con otros objetos, se puede formar una estructura muy compleja, con objetos con muchas conexiones con otros objetos. En un caso extremo cada objeto puede conocer a todos los demás objetos. Para evitar esto el patrón Mediator encapsula el comportamiento de todo un conjunto de objetos en un solo objeto.

Estructura

Participantes
Mediator
Define una interface para comunicarse con los objetos colegas.
ConcreteMediator
Implementa el comportamiento cooperativo entre los colegas (como se comunican entre ellos). Además los conoce y mantiene.
Colleagues
Cada colega conoce su mediador, y usa a este para comunicarse con otros colegas.

Consecuencias

El patrón Mediator tiene los siguientes beneficios y desventajas:
Desacopla a los colegas: el patrón Mediator promueve bajar el acoplamiento entre colegas. Se puede variar y reusar colegas y mediadores independientemente
Simplifica la comunicación entre objetos: Los objetos que se comunican de la forma "muchos a muchos" puede ser remplazada por una forma "uno a muchos" que es menos compleja y más elegante. Además esta forma de comunicación es más fácil de entender.
Abstrae como los objetos cooperan: Haciendo a la mediación un concepto independiente y encapsulandolo en un objeto permite enfocar como los objetos interactúan. Esto ayuda a clarificar como los objetos se relacionan en un sistema.
Centraliza el control: El mediador es el que se encarga de comunicar a los colegas, este puede ser muy complejo, difícil de entender y modificar


Memento
Intención
Guardar una el estado de un objeto, de forma que pueda ser devuelto a su estado original sin revelar su contenido al resto del mundo.

Motivación

Muchas veces es necesario guardar el estado interno de un objeto. Esto debido a que tiempo
después, se necesita restaurar el estado del objeto, al que previamente se ha guardado.
Consideremos por ejemplo una aplicación de composición de figuras geométricas, donde
el usuario hace sucesivas modificaciones a una composición, graficando nuevas líneas, círculos y rectángulos. Después de cierto tiempo, el usuario logra una composición “casi perfecta”, pero decide alcanzar la perfección, así que pinta una línea y esta no le sale como él esperaba. Definitivamente el usuario quisiera regresar al instante en que su “creación” era una obra de arte. Para dar solución a este problema, antes de que el usuario agregue una
nueva figura geométrica a la composición, se debería guardar el estado de la composición y entonces siempre se tendría la posibilidad de regresar hacia atrás y restaurar la composición a su estado anterior.
Para lograr esto, sería necesario guardar la lista de figuras geométricas y el orden en que se encuentran en la composición, con información específica de cada una de ellas. En el caso de un círculo tendríamos que guardar la posición (x, y), el radio, color y relleno, para un rectángulo la posición (x, y), el ancho, el largo, color y relleno. Para lograr esto tenemos tres alternativas: la primera alternativa consiste en obtener la lista de figuras de la composición y
obtener su estado, esto sería muy complejo y además va en contra del principio de encapsulamiento; la segunda alternativa, es que la composición se encargue de ir guardando su estado interno cada vez, esta no es una buena alternativa, la clase sería muy compleja y estaría asumiendo responsabilidades que no le corresponden; la tercera alternativa es la mejor, composición (Originator) crea un objeto (Memento) y almacena su estado interno en él, la aplicación (Caretaker) mantiene una lista de los objetos (Memento), de tal manera que
cuando el usuario realice una operación de “deshacer”, la aplicación restaure el estado de la composición (Originator), con lo almacenado por el objeto Memento.

Estructura

Participantes
Memento
Almacena el estado interno de un objeto Originator. El Memento puede almacenar mucho o parte del estado interno de Originator.
Tiene dos interfaces. Una para Caretaker, que le permite manipular el Memento únicamente para pasarlo a otros objetos.
La otra interfaz sirve para que Originator pueda almacenar/restaurar su estado interno, sólo Originator puede acceder a esta interfaz, al menos en teoría.
Originator
Originator crea un objeto Memento conteniendo una fotografía de su estado interno.
Originator usa a Memento para restaurar su estado interno.
Caretaker
Es responsable por mantener a salvo a Memento.
No opera o examina el contenido de Memento.

Consecuencias
• Originator crea un Memento y el mismo almacena su estado interno, de esta manera no es necesario exponer el estado interno como atributos de acceso público, preservando así la encapsulación.
• Si Originator tendría que de almacenar y mantener a salvo una o muchas copias de su estado interno, sus responsabilidades crecerían y serían más complejas, se desviaría de su propósito disminuyendo la coherencia. Usar Mementos hace que Originator sea mucho más sencillo y coherente.
• El uso frecuente de Mementos para almacenar estados internos de gran tamaño, podría resultar costoso y perjudicar el rendimiento del sistema.
• Caretaker al no conocer detalles del estado interno de Originator, no tiene idea de cuanto espacio y tiempo se necesita para almacenar el estado interno de Originator en un Memento y restaurar su estado interno a partir de un Memento. Por lo que no puede hacer predicciones de tiempo ni de espacio.
• Memento debería proporcionar una interfaz privada, a la que sólo Originator puede acceder. Esta interfaz incluye la creación, el almacenamiento y recuperación del estado interno de Originator. Además una interfaz pública que permita la destrucción de Memento.


Observer

Intención
proporcionar a los componentes una forma flexible de enviar mensajes de difusión a los receptores interesados.

Motivación

Al dividir sistema en colección de clases cooperantes:
• Necesidad de mantener la consistencia entre los objetos
relacionados.
• Evitar fuerte acoplamiento entre clases.
Las clases que definen los datos de las aplicaciones y las
representaciones pueden reutilizarse de forma independiente.
Objetos participantes: sujeto y observadores.
Cada vez que el sujeto cambia su estado se notifica a todos
sus observadores.

Estructura


Participantes
Subject
Conoce a sus observadores. Cualquier número de Observación de los objetos puede observar un objeto.
Provee una interfaz para conectar y desconectar de Observación de los objetos.
Observer
Define una interfaz para la actualización de los objetos que deben ser notificados de los cambios en un tema.
ConcreteSubject
Las tiendas estatales de interés para ConcreteObserver objetos.
Envía una notificación a sus observadores cuando su estado cambia.
ConcreteObserver
Mantiene una referencia a un objeto ConcreteSubject.
Las tiendas del Estado que debe mantenerse en consonancia con la del sujeto.
Se aplica la actualización de la interfaz de Observadores para mantener su estado en consonancia con la del sujeto.

Consecuensias
Ventajas:
Permite modificar las clases subjects y las observers independientemente. Se pueden rehusar clases subjects sin rehusar sus clases observers.
Permite añadir nuevas clases observers a una clase subject que ya tenía asociadas unas clases observers sin modificar la clase subject o alguno de esas clases observers que ya tenía.
Permite que dos capas de abstracción de diferentes niveles de abstracción se puedan comunicar entre sí sin romper esa división en capas de abstracción. Por ejemplo, en el caso de las capas de Presentación y Dominio.
Permite comunicación broadcast, es decir, un objeto subject envía su notificación a todos los objetos observers que lo estén observando sin enviárselo a ningún observer en concreto (el mensaje no tiene un destinatario concreto). Todos los observers reciben el mensaje y deciden si hacerle caso ó ignorarlo.
Desventajas:
El protocolo de comunicación entre los objetos subject y sus objetos observers es muy pobre: el evento siempre es que se ha producido algún cambio en el estado del objeto subject, el mensaje no indica el destinatario (siempre es broadcast) y tampoco indica qué es lo que ha cambiado en el objeto subject (y, entonces, son sus objetos observers los que tienen que deducir qué es lo que ha cambiado en el objeto subject sin ayuda de éste, si así lo desean; lo que puede introducir gran complejidad computacional en los observers).
Aumenta el número de clases necesarias para implementar la aplicación y disminuye la comprensibilidad de ésta.
Los observers dependen del subject al que observan, pues lo conocen (hacen referencia a él), por lo que cambios en la clase del subject pueden provocar cambios en las de los observers.


State
intención
Cambiar fácilmente el comportamiento de un objeto en tiempo de ejecución.

Motivación

El patrón State está motivado por aquellas clases que, según su estado actual varía su comportamiento ante los diferentes mensajes. Como ejemplo se toma una clase TCPConection la que representa una conexión de red, un objeto de esta clase tendrá diferentes respuestas según su estado (Listening, Close o Established). Por ejemplo una llamada al método Open de un objeto de la clase TCPConection diferirá su comportamiento si la conexión se encuentra en Close o en Established.

Estructura

Participantes
• Context
Este integrante define la interfaz con el cliente. Mantiene una instancia de ConcreteState (Estado Concreto) que define su estado actual
State
Define una interfaz para el encapsulamiento de la responsabilidades asociadas con un estado particular de Context.
Subclase ConcreteState
Cada una de estas subclases implementa el comportamiento o responsabilidad de Context.
El Contexto delega el estado específico al objeto ConcreteState actual Un objeto Context puede pasarse a sí mismo como parámetro hacia un objeto State. De esta manera la clase State puede acceder al contexto si fuese necesario. Context es la interfaz principal para el cliente. El cliente puede configurar un contexto con los objetos State. Una vez hecho esto, los clientes no tendrán que tratar con los objetos State directamente. Tanto el objeto Context como los objetos de ConcreteState pueden decidir el cambio de estado

Consecuencias
Se encuentran las siguientes ventajas:
Se localizan fácilmente las responsabilidades de los estados específicos, dado que se encuentran en las clases que corresponden a cada estado. Esto brinda una mayor claridad en el desarrollo y el mantenimiento posterior. Esta facilidad la brinda el hecho que los diferentes estados están representados por un único atributo (state) y no envueltos en diferentes variables y grandes condicionales.
Hace los cambios de estado explícitos puesto que en otros tipos de implementación los estados se cambian modificando valores en variables, mientras que aquí al estar representado cada estado.
Los objetos State pueden ser compartidos si no contienen variables de instancia, esto se puede lograr si el estado que representan esta enteramente codificado en su tipo. Cuando se hace esto estos estados son Flyweights sin estado intrínseco.
Facilita la ampliación de estados
Permite a un objeto cambiar de clase en tiempo de ejecución dado que al cambiar sus responsabilidades por las de otro objeto de otra clase la herencia y responsabilidades del primero han cambiado por las del segundo.
Se encuentran la siguiente desventaja:
Se incrementa el número de subclases.


Strategy
Intención
Definir una familia de algoritmos, encapsularlos y hacerlos intercambiables

Motivación
Muchas clases relacionadas difieren sólo en su comportamiento
Se necesitan distintas variantes del mismo algoritmo
Una clase define muchos comportamientos

Estructura

Participantes
Strategy
Declara una interfaz común a todos los algoritmos soportados
ConcreteStrategy
Implementa el algoritmo que que usa la interfaz strategy.
Context
Se configuran con un objeto ConcreteStrategy
Mantiene una referencia a un objeto Strategy
Puede definir una interfaz que permite acceder a sus datos

Consecuencias
Es una alternativa a la herencia
Eliminan estructuras condicionales
Selección de implementaciones.


Template Method

Intención
Usando el Template Method, se define una estructura de herencia en la cual la superclase sirve de plantilla de los métodos en las subclases. Una de las ventajas de este método es que evita la repetición de código, por tanto la aparición de errores.

Motivación
Este patrón se vuelve de especial utilidad cuando es necesario realizar un algoritmo que sea común para muchas clases, pero con pequeñas variaciones entre una y otras.

Estructura

Participantes
AbstractClass
Resumen define las operaciones primitivas que concretesubclasses definir para la aplicación de medidas de un algoritmo.
Aplica un método de definición de la plantilla de un esqueleto algoritmo. La plantilla llamadas a los métodos primitivos de operaciones, así como operaciones definidas en AbstractClass o los de otros objetos.
ConcreteClass
se aplica la primitiva para llevar a cabo operaciones específicas de la subclase de los pasos del algoritmo.

Consecuencias
Facilita la reutilización de código. Sin el método plantilla, el código se duplica en muchas subclases. Esta ventaja hace que el patrón sea fundamental en muchos frameworks. El uso del patrón implica que la estructura completa puede ser proporcionada por el Framework, solo tendrá que redefinir unos pocos métodos para poder ser utilizado.
Si el método plantilla llama a demasiados métodos abstractos, se cansara pronto de utilizar AbstractClass como superclase. Es mejor hacer que el método plantilla llame a un numero limitado de métodos abstractos.


Visitor
Intención
Representa una operación que se realiza sobre los elementos que conforman la estructura de un objeto. Visitor permite definir nuevas operaciones sin cambiar las clases de los elementos en los que opera.

Motivación

Un compilador representa los programas como árboles de sintaxis abstracta, sobre los que ejecuta operaciones
Muchas operaciones necesitan diferenciar distintos tipos de nodo en el árbol (expresiones, variables, etc.)

Estructura

Participantes
Visitor
define una operación de visita para cada clase de elemento concreto en la estructura de objetos
ConcreteVisitor
Implementa la interfaz Visitor
Cada operación implementa un fragmento de la labor global del visitor concreto, pudiendo almacenar información local
Element
define una operación accept con un visitor como argumento
ConcreteElement
implementa la operación accept
ObjectStructure
Gestiona la estructura de objetos, y puede enumerar sus elementos
Puede ser un compuesto (patrón composite) o una colección de objetos
Puede ofrecer una interfaz que permita al visitor visitar a sus elementos

Consecuencias
Facilita la definición de nuevas operaciones.
Agrupa operaciones relacionadas.
Añadir nuevas clases ConcreteElement es costoso.
Utilizar el patrón visitor si la jerarquía de clases es estable.
Permite atravesar jerarquías de objetos que no están relacionados por un padre común.
El visitor puede acumular el estado de una operación al visitar la estructura de objetos, en vez de pasarlo como argumento o usar variables globales.
Rompe la encapsulación.

martes, 19 de mayo de 2009

ESTRUCTURALES

Adapter

Intención
Adapta una interfaz para que pueda ser utilizada por una clase que de otro modo no podría utilizarla.

Motivacion
Necesitamos reutilizar clases ajenas paranuestro sistema, pero aunque la funcionalidad de estas clases es la que deseamos, la interfaz no es compatible. Si no podemos o no queremos modificar las clases a reutilizar, necesitamos hacerlas compatibles con nuestro sistema.

Aplicabilidad

Se quiere utilizar una clase que llame a un método a través de una interface, pero quieres utilizarlo con una clase que no implementa ese interface. Modificar esa clase que implementa el interface no es una opción por un par de razones:
1. No tienes el código fuente de la clase.
2. La clase es una clase de propósito general, y es inapropiado para ella implementar un interface par un propósito específico.
Se quiere determinar dinámicamente que métodos de otros objetos llama un objeto.
Se quiere realizarlo sin que el objeto llamado tenga conocimientos de la otra clase de objetos.

Estructura


Participantes
Target: Define la interfaz especifica del dominio en el que se quiere hacer uso de la clase que se adapta.
Client: Utiliza objetos que implementan la interfaz definida por el target.
Adaptee: Presenta su interfaz original, que es la que se tiene que adaptar.
Adapter: Adapta la interfaz del objeto adaptado a la definida por el target.

Colaboraciones
Esta sección está compuesta por máximo seis (6) palabras o frases que describan los tópicos, áreas o temas más importantes del trabajo. Deben estar ordenadas alfabéticamente. La selección de palabras clave apropiadas permitirá la inclusión del artículo en índices internacionales así como la ubicación rápida del artículo por parte de un lector interesado.

Consecuencias
El cliente y las clases Adaptee permanecen independientes unas de las otras.
El patrón Adapter introduce una in dirección adicional en un programa . Como cualquier otra in dirección, contribuye a la dificultad implicada en la compresión del programa.
Se puede utilizar una clase Adapter para determinar cuales de los métodos de un objeto llama otro objeto.
Adaptadores de clase y el objeto tienen diferentes ventajas y desventajas. A class adapter Una clase adaptador

Adaptee se adapta al objetivo de la comisión a una clase concreta adaptador. Como consecuencia de ello, una clase
adaptador no funciona cuando se quiere adaptar una clase y todas sus subclases.

Adaptador permite anular algunas de Adaptee el comportamiento, ya que el adaptador es una subclase de Adaptee.
sólo introduce un objeto, y no puntero indirección adicional es necesaria para llegar a la adaptee.
Un objeto adaptador
permite a un único adaptador de trabajar con muchas Adaptees-es decir, la Adaptee sí mismo y todas sus subclases
(si procede). El adaptador también puede agregar funcionalidad a todos los Adaptees a la vez.
Adaptador se refieren a la subclase más que la propia Adaptee

Implementación
La implementación de una clase Adapter es más bien sencilla. Sin embargo, una cuestión que deberías considerar cuando implementes el patrón Adapter es como los objetos adapter conocen que instancia de la clase Adaptee llamar. Hay dos métodos:

1. Pasar una referencia a los objetos cliente como parámetro a los costructores de los objetos adapter o a uno de sus métodos. Esto permite al objeto adapter ser utilizado con cualquier instancia o posiblemente muchas instancias de la clase Adaptee.
Hacer la clase Adapter una clase interna de la clase Adaptee. Esto simplifica la asociación entre el objeto adapter y el objeto adaptee haciendolo automático.
También hace la asociación inflexible.

Código ejemplo
public interface ListModel {
int getSize();
Object getElementAt(int index);
}
public interface TableModel {
public int getRowCount();
// obtener número de filas
public int getColumnCount();
// obtener número de columnas
public Object getValueAt(int fil, int col);
// retorna valor del elemento fila fil y columna col
public String getColumnName(int col);
// retorna nombre de la columna col
}

Usos conocidos
El API de Java no incluye ningún objeto adapter público que este listo para utilizar. Incluye clases tales como java.awt.event.WindowAdapter que pretenden ser heredadas más que utilizarse directamente. La idea es que hay algunos interfaces escuchadores de eventos, tales como WindowListener, que declaran varios métodos. En muchos casos no todos los métodos necesitan ser implementados. El interface WindowListener declara ocho métodos que son llamados para proporcionar notificación sobre los ocho tipos diferentes de eventos de la ventana. A menudo uno o dos de estos tipos de eventos son de interés. Los métodos que corresponden a los eventos que no son de interés normalmente están dando implementaciones de no hacer nada. La clase WindowAdapter implementa el interface WindowListener e implementa los ocho métodos con implementaciones de no hacer nada. Una clase Adapter que hereda la clase WindowAdapter necesita implementar solamente los métodos que corresponden a los eventos que son de interés. Hereda las implementaciones de no hacer nada para el resto.

Patrones relacionados

Facade
La clase Adapter proporciona un objeto que actúa como un intermediario para llamar a los métodos entre los objetos cliente y uno de los otros objetos que no conocen a los objetos cliente. El patrón Facade proporciona un objeto que actúa como un intermediario para llamar a los métodos entre los objetos cliente y múltiples objetos que no conocen a los objetos cliente.
Iterator
El patrón Iterator es un versión especializada del patrón Adapter para acceder secuencialmente al contenido de una colección de objetos.
Proxy
El patrón Proxy, como el patrón Adapter, utiliza un objeto que es un sustituto por otro objeto. Sin embargo, un objeto proxy tiene el mismo interface que el objeto por el que es sustituido.
Strategy
El patrón Strategy es estructuralmente similar al patrón Adapter. La diferencia esta en el objetivo. El patrón Adapter permite a un objeto cliente exportar su función deseada originalmente para llamar al método de los objetos que implementan un interface particular. El patrón Strategy proporciona objetos que implementan un interface particular con el propósito de alterar o determinar el comportamiento de un objeto cliente.



Bridge

Intención
desacopla una abstracción de su implementación para que puedan variar independientemente.

Motivación
Cuando queremos que un objeto cambie su comportamiento, según cambia su estado, se presenta el problema de la complejidad de código.

Aplicabilidad
Se usa el patrón Bridge 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.
(En C++) Se desea esconder la implementación de una abstracción completamente a los clientes. En C++, la representación de una clase es visible en la interface de la clase.
Se desea compartir una implementación entre múltiples objetos (quizá usando contadores), y este hecho debe ser escondido a los clientes.

Estructura

Participantes
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 diferente. Típicamente la interface Implementor provee sólo operaciones primitivas, y Abstraction define operaciones de alto nivel basadas en estas primitivas.
ConcreteImplementor implementa la interface de Implementor y define su implementación concreta.

Colaboraciones
Abstraction emite los pedidos de los clientes a su objeto Implementor.
Consecuencias
Un objeto puede cambiar su implementación en tiempo de ejecución.
Cambios en la implementación no requerirán compilar de nuevo la clase Abstracción y sus clientes.
Se mejora la extensibilidad.
Se ocultan detalles de implementación a los clientes.

Implementación
Sólo un Implementor: en situaciones donde existe sólo una implementación, crear una clase Implementor abstracta no es necesario. Esto es un caso especial del patrón; hay una relación uno-a-uno entre Abstraction e Implementor. Sin embargo, esta separación es aún muy útil cuando un cambio en la implementación de una clase no debe afectar a sus clientes existente, es decir, ellos no deben ser recompilados, sólo relinkeados. En C++, la interface de la clase Implementor puede ser definida en un archivo header privado el cual no es proveído a los clientes. Esto permite esconder una implementación de una clase completamente de sus clientes.
Creando el objeto Implementor adecuado: ¿Cómo, cuándo y dónde que clase Implementor instanciar cuando hay más de una?Si Abstraction conoce todas las clases ConcreteImplementor puede instanciar una de ellas en su constructor; puede decidir cuál instanciar dependiendo de los parámetros del constructor.
Otra aproximación es elegir una implementación inicial por defecto y cambiarla después acorde al uso. También es posible delegar la decisión a otro objeto en conjunto.
Compartiendo implementadores: el estilo Handle/Body en C++ puede ser usado para compartir implementaciones de muchos objetos. Body almacena una cuenta de referencia que la clase Handle incrementa y decrementa. Usando herencia múltiple. Se puede usar herencia múltiple en C++ para asociar una interfaz con su implementación.
Creamos una clase Abstracción padre que sea abstracta, además de abstracciones concretas mediante clases que heredan de ella. Por otro lado se tienen las clases que implementan la funcionalidad con una estructura similar: una clase ImplementaciónAbstracta padre, y todas las clases hijas necesarias que implementan la funcionalidad de todas las maneras necesarias. La relación se da entre la clase abstracta Abstracción y la clase abstracta Implementación, delegando la primera la implementación en la segunda, que a su vez la delega en las implementaciones concretas.

Código ejemplo
//método getToolkit en Component

public Toolkit getToolkit() {
return getToolkitImpl();
}
final Toolkit getToolkitImpl() {
ComponentPeer peer = this.peer;
if ((peer != null) && ! (peer instanceof LightweightPeer)){
return peer.getToolkit();
}
Container parent = this.parent;
if (parent != null) {
return parent.getToolkitImpl();
}
return Toolkit.getDefaultToolkit();
}
//método getDefaultToolkit en la clase Toolkit

public static Toolkit getDefaultToolkit() {
String nm;
Class cls;
if (toolkit == null) {
try { nm = System.getProperty("awt.toolkit",
"sun.awt.motif.MToolkit");
try { cls = Class.forName(nm);
} catch (ClassNotFoundException e){..}
if (cls != null) toolkit = (Toolkit) cls.newInstance();
...
return toolkit;
}

Usos conocidos
El AppKit de NeXT usa un Bridge en la visualización de diferentes tipos de imágenes.
El DOM de KDE3 esta basado en un bridge (con otros patrones). Permite crear diferentes tipos de documentos usando la misma abstracción.
Patrones relacionados
AbstractFactory.
· Adapter.




Composite


Intención

Componer objetos en estructuras de árbol para representar jerarquías parte-todo.
Composite permite a los clientes tratar cada uno de los objetos y composiciones de objetos de manera uniforme.

Motivación
El problema que trata
Para constituir diagramas complejos desde componentes
simples en casos como un editor de dibujos, diseñador de
circuitos
Los objetos primitivos y los contenedores de ellos están en
diferentes maneras, aunque los clientes tratan ambos en la
misma manera.

Aplicabilidad
Cuando necesitamos representar la relación parte-todo

Cuando queramos que los clientes olviden la diferencia entre
las composiciones de objetos y los objetos individuales


Estructura


Participantes
Componente
Declara la interfaz para los clientes puedan acceder a lo objetos en la composición
Implementa comportamientos por defectos para todas las clases

Hoja
Representa los objetos hoja en la composición. No tienen hijos.

Define el comportamiento de los objetos primitivos en la composición

Compuesto
Define el comportamiento para los componentes que tienen
hijos
.
Almacena los componentes hijos


Implementa operaciones relacionadas a los hijos en la interfaz
de Componente
. Cliente

Manipula los objetos en la composición a través de la interfaz
de la clase Componente
.

Colaboraciones

Existen colaboraciones entre el cliente y
Componente

El cliente utiliza la interfaz para interactuar
con los objetos en la composición

Si el recibidor es una hoja: la petición se
trata directamente

Si el recibidor es un Compuesto: la petición
se pasa a sus hijos

Puede tener más operaciones extras


Consecuencias

Se define una jerarquía de clases con objetos
primitivos y compuestos

Simplifica las tareas del cliente. Puede tratar un
compuesto como un objeto primitivo

Facilita añadir nuevos componentes sin modificar
la estructura ni los códigos de clientes

Desventajas:

El diseño de programa puede ser demasiado
general

Difícil de restringir los componentes de un
compuesto.


Implementación


Temas para considerar en la implementación:

Referencias explícitas al padre

Es conveniente a tener la referencia al padre para simplificar el recorrido y administración hacia arriba

Compartir componentes

Para ahorrar espacio de almacenamiento

Será difícil a compartir cuando el componente tiene un sólo
padre

La solución aparece en el patrón Flyweight
Maximizar la interfaz de Componente.

Es bueno a definir más operaciones posibles en la clase
Componente tanto para Compuesto como para Hoja

Definir operaciones por defectos en Componente y luego las
subclases puedan redefinirlas si son necesarias.

Dónde declarar las operaciones para administrar los hijos

Definir en la raíz (Componente): mejor transparencia peor
seguridad porque los clientes pueden hacer cosas raras

Definirlas en Compuesto: mejor seguridad pero pierde la
transparencia

Una solución: verificar en la interfaz si lo que pide es un
Compuesto o una hoja.

Código ejemplo

public abstract class Componente
{
protected String nombre;
public Componente (String nombre)
{
this.nombre = nombre;
}
abstract public void Agregar(Componente c);
abstract public void Remover(Componente c);
abstract public void Mostrar(int profundidad);
}
class Compuesto extends Componente
{
private ArrayList hijo = new ArrayList();
public Compuesto (String name)
{
super(name);
}
@Override
public void Agregar(Componente componente)
{
hijo.add(componente);
}
@Override
public void Remover(Componente componente)
{
hijo.remove(componente);
}
@Override
public void Mostrar(int profundidad)
{
System.out.println(nombre + " nivel: " + profundidad);
for (int i = 0; i < raiz =" new" comp =" new" l =" new" style="font-weight: bold;" size="4">Usos conocidos

n Java:
· las clases java.awt.Component(Componente)
· java.awt.Container(Contenedor)
· java.awt.Panel(Contenedor concreto)
· java.awt.Button(Boton)

Patrones relacionados
Chain of Responsibility: para crear enlace entre la

clase componente y su padre

Decorator: se suelen utilizar con composite.
Normalmente tienen una clase pariente en comúm

Flyweight: nos permite compartir componentes, pero
sin referencias a su pariente

Iterator: se puede utilizar para recorrer los
compuestos

Visitor: puede localizar operaciones y
comportamientos sin distribuirlos entre las clases de
Compuesto y Hoja



Decorator

Intención
Fija responsabilidades adicionales a un objeto dinámicamente. Decoreirtors provee una alternativa flexible a las subclasses para extender la funcionalidad.

Motivación
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.

Aplicabilidad

Añadir objetos individuales de forma dinámica y transparente
Responsabilidades de un objeto pueden ser retiradas
Cuando la extensión mediante la herencia no es viable
Hay una necesidad de extender la funcionalidad de una clase, pero no hay razones para extenderlo a través de la herencia.
Hay la necesidad de extender dinámicamente la funcionalidad de un objeto y quizás quitar la funcionalidad extendida.

Estructura

Participantes
Component
Define la interface de los objetos a los que se les pueden adicionar responsabilidades dinámicamente.
ConcreteComponent
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.
ConcreteDecorator
Adiciona la responsabilidad al Component.

Colaboraciones

Decorator envía las solicitudes a su componente de objeto. Opcionalmente puede realizar operaciones adicionales antes y después del envío de la solicitud.

Consecuencias
Ventajas

1.Es más flexible que la Herencia estática.
2.Permite que la adicion de nuevas responsabilidades (nuevas clases de Decorators) independiente de las clases los Objetos que ellas extienden.
Desventajas
1.Un Decorator y su Component no son idénticos. Desde el punto de vista de la identidad de los objetos, un DecoratorComponent no es identico al Component. Por esto no se puede confiar en en la identidad de los objetos cuando se usan Decorators
2.El patrón Decorator hace que hayan muchos objetos pequeños que son muy parecidos.

Implementación
El patrón Decorator soluciona este problema de una manera mucho más sencilla y extensible.
Se crea a partir de Ventana la subclase abstracta VentanaDecorator y, heredando de ella, BordeDecorator y BotonDeAyudaDecorator. VentanaDecorator encapsula el comportamiento de Ventana y utiliza composición recursiva para que sea posible añadir tantas "capas" de Decorators como se desee. Podemos crear tantos Decorators como queramos heredando de VentanaDecorator.


Código ejemplo
public abstract class FilterReader extends Reader {
protected Reader in;
protected FilterReader(Reader in) {
super(in);
this.in = in; }
public int read() throws IOException {
return in.read(); }
… }

public class ConversorMayúsculas extends FilterReader {
public ConversorMayúsculas (Reader in) {
super(in);
}
public int read() throws IOException {
int c = super.read();
if (c != -1) return Character.toUpperCase((char)c);
else return c;
}
}

Usos conocidos
Muchos toolkits de interfaz de usuarios orientado aobjetos utilizan Decorator para añadir decoraciones graficas.

Patrones relacionados
Adapter: Este patrón cambia las responsabilidades y la interfaces de un objeto.
1.Composite: Un DECORATOR se puede mirar como un COMPOSITE de un solo elemento.
2.Strategy: Este patrón permite cambiar el contenido de los Objetos par agregar responsabilidades.

Facade

Intención
Proporcionar una interfaz unificada a un conjunto de interfaces en un subsistema. Fachada define una interfaz de alto nivel que hace que el subsistema sea más fácil de usar.

Motivación
Minimizar la comunicación y las dependencias entre subsistemas

Aplicabilidad
El uso de este patrón esta recomendado para
Simplicar el uso y comprensión de una librería software.
Encapsular un interfaz de librería poco amigable en un interfaz más coherente o mejor estructurado.
Centralizar las dependencias externas hacia la librería en uno o pocos puntos de entrada.

Estructura


Participantes

Fachada
subsistema o sabe que las clases son responsables de una solicitud.
delegados a las solicitudes de cliente subsistema objetos.
subsistema de clases
implementar la funcionalidad del subsistema.
manejar el trabajo asignado por la Fachada objeto.
no tienen conocimiento de la fachada, es decir, no mantener las referencias a la misma.

Colaboraciones
Los clientes se comunican con el subsistema mediante el envío de peticiones a la fachada, que reenvía a los subsistema objeto (s). A pesar de que el subsistema de objetos de realizar el trabajo real, la fachada puede tener que hacer su propio trabajo de traducir su interfaz a las interfaces del subsistema.
Los clientes que usan la fachada no tiene acceso a su subsistema de objetos directamente.

Consecuencias

la ventaja del patrón facade es que proporciona una interfaz mas simple para un sistema complejo sin reducir las opciones proporcionadas por el conjunto del sistema. Esta interfaz protege al cliente de la sobreabundancia de opciones.
El patrón Facade traduce las peticiones del cliente a los subsistema que pueden cumplir esas peticiones. La mayor parte de las veces, una petición sera delegada en mas de un sistema. Como el cliente Solo interactúa con el facade, el funcionamiento interno puede ser modificado, mientras que el cliente del facade puede permanecer igual.
El patrón Facade fomenta el bajo acoplamiento entre el cliente y los subsistemas. También puede ser utilizado para reducir el acoplamiento entre los subsistemas. Todos los subsistemas pueden tener su propio Facade, y las otras partes del sistema pueden utilizar ese Facade para comunicarse con el subsistema.

Implementación

Se puede reducir aún más el acoplamientohaciendo que la fachada sea una clase abstracta, de forma que se pueda escogerentre distintas implementaciones del subsistema


Código ejemplo





Usos conocidos

Las clases Font y Graphics de las librerías estandar de Java que proporcionan la funcionalidad básica para manipulación de fuentes y graficos aislando al usuario, en las operaciones más comunes, de la complejidad subyacente. Otros ejemplos incluyen determinados interfaces de librerías GIS o librerías matemáticas.

Patrones relacionados
Abstract factory : para simplificar el acceso a los distintos objetos creados por la fabrica , esta también puede crear un objeto facade para todos ellos.
Mediator: los patrones mediator y facade son muy parecidos . La diferencia reside en la intención y en la implementación. El patrón mediator ayuda a facilitar la comunicación entre los componentes y sus comportamientos adicionales.
Singleton: el patrón facade utiliza el patrón Singleton para garantizar un punto de entrada único y globalmente accesible para un subsistema.

Flyweight

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

Motivación
El patrón flyweight describe como 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

Se debe aplicar este patrón cuando se cumplen todas estas 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 aplicación no depende de la identidad de los objetos.

Estructura

Participantes
Flyweight
Declara una interfaz a través de la cual los flyweights pueden recibir y actuar sobre los 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.
Calcula o almacena los estados no compartidos de los flyweights.

Colaboraciones

Un objeto flyweight debe ser clasificado como compartido o no compartido. Los compartidos se almacenan en el objeto ConcreteFlyweight; los no compartidos se almacenan o se calculan en el objeto Cliente. Los clientes pasan este estado al objeto flyweight cuando invocan sus operaciones.
Los clientes no deberían instanciar objetos de la clase ConcreteFlyweight directamente. Deben obtenerlos exclusivamente del objeto FlyweightFactory para garantizar que son compartidos apropiadamente.

Consecuencias
A primera vista , la ventaja que se obtiene es que se reduce el numero de objetos que hay que gestionar. Esto puede ahorrar mucho espacio, tanto en memoria como en los dispositivos de almacenamiento en caso de que sean objetos persistentes.
Se ahorra mas espacio aun si la información de contexto para los objetos Flyweight se calcula en vez de tener la almacenada, sin embargo , esto nos lleva al inconveniente de este patrón: el costo en tiempo de ejecución.
En lugar de almacenar muchos objetos, los clientes tienen que calcular el contexto y proporcionar esa información a los objetos Flyweight. Los Flyweight utilizan esta información para proporcionar funciones. Si se maneja menos objetos y se implementa correctamente, se incrementa el rendimiento en tiempo de ejecución . Obsérvese que si hay, poca información de contexto y el objeto Flyweight es grande , el ahorro es significativo.

Implementación

Crear una clase PelotaFlyweight, que contendrá la información común (radio y color) y otra clase PelotaConcreta, que contendrá las coordenadas concretas de cada pelota y una referencia a un objeto de tipo PelotaFlyweight.
Al crearse instancias de PelotaConcreta, se les deberá proveer de referencias a la instancia de PelotaFlyweight adecuada a nuestras necesidades.
En este caso solamente tendríamos una instancia de PelotaFlyweight, puesto que hemos dicho que todas nuestras pelotas tienen el mismo radio y color, pero pensando en un ejemplo en el que tuviéramos varios grupos de pelotas, y dentro de cada uno de los cuales se compartieran el radio y el color, se puede utilizar Flyweight conjuntamente con el patrón Factory, de tal modo que este último, en el momento en que se le soliciten instancias de PelotaConcreta con determinadas características (mismo radio y color que el solicitado), compruebe si ya existe un PelotaFlyweight con ese radio y color, y devuelva esa referencia o, en caso de que no exista, la cree y la registre. El patrón Factory se encargaría de gestionar los PelotaFlyweight existentes.

Código ejemplo
public class Elemento {
public Elemento() {..}
public void mostrar (Window w, ElemContexto ec) {..}
public void setFont (Font f, ElemContexto ec) {..}
public Font getFont (ElemContexto ec) {..}
public void insert (ElemContexto ec, Elemento e) {..}
...
}
public class Caracter extends Elemento {
char code;
public Caracter(char c) {..}
public void mostrar (Window w, ElemContexto ec) {..}
}


public class ElemContexto {
int index;
Btree fonts;

public ElemContexto() {...}
public void setFont (Font f, int span) {..}
public Font getFont () {..}
public void insert (int cant) {..}
public void next (){..}
}

Usos conocidos

Strings
Pool de objetos compartidos para literales de tipo String
“hola” = “hola”
Método intern() en clase String: dado un string lo añade al pool
String c = (a+b).intern
Bordes de Swing

Patrones relacionados Composite, utilizado para componer objetos en estructural de árbol para representar jerarquías.

Proxy, que proporciona un intermediario de otro objeto para controlar el acceso a este. º
Facade, que proporciona una interfaz unificada para un conjunto de interfaces de un subsistema.

Proxy


Intención
Proporcionar un sustituto o marcador de posición de otro objeto para controlar el acceso a ella.

Motivación
Diferir el coste de crear un objeto hasta que sea necesario usarlo: creación bajo demanda.
Un editor de documentos que incluyen objetos gráficos.
¿Cómo ocultamos que una imagen se creará cuando se necesite?: manejar el documento requiere conocer información sobre la imagen.
Hay situaciones en las que un cliente no referencia o no puede referenciar a un objeto directamente, pero necesita interactuar con él.
Un objeto proxy puede actuar como intermediario entre el objeto cliente y el objeto destino.
El objeto proxy tiene la misma interfaz como el objeto destino.
El objeto proxy mantiene una referencia al objeto destino y puede pasarle a él los mensajes recibidos (delegación).
Retrasar la operación de una clonación de una tabla hasta conocer que es realmente necesaria. Se desea clonar la tabla para evitar mantener un bloqueo un largo período de tiempo: operación costosa. Se puede crear una clase que encapsule la tabla y sólo clone cuando sea necesario.
Mantenimiento de los servicios ante los fallos.
Materialización perezosa de tuplas en objetos.

Aplicabilidad

Siempre que hay necesidad de referenciar a un objeto mediante una referencia más rica que un puntero o una referencia normal.
Situaciones comunes;

Proxy acceso remoto (acceso a un objeto en otro espacio de direcciones)
Proxy virtual (crea objetos grandes bajo demanda)
Proxy para protección (controlar acceso a un objeto)
Referencia inteligente (smart reference, proporciona operaciones adicionales)

Estructura

Participantes
Sujeto:
Define la interfaz común para el RealSubject y el Proxy, de modo que pueda usarse un Proxy en cualquier sitio en el que se espere un RealSubject.

RealSubject:
Define el objeto real representado.
Proxy:
Mantiene una referencia que permite al Proxy acceder al objeto real.
Proporciona una interfaz idéntica a la del sujeto, de manera que un Proxy pueda ser sustituido por el sujeto real.
Controla el acceso al sujeto real, y puede ser responsable de su creación y borrado.

Colaboraciones
Proxy reenvía las solicitudes de RealSubject en su caso, dependiendo del tipo de proxy.
Consecuencias
Introduce un nivel de indirección para:

Un proxy remoto oculta el hecho que objetos residen en diferentes espacios de direcciones.
Un proxy virtual tales como crear o copiar un objeto bajo demanda.
Un proxy para protección o las referencias inteligentes permiten realizar tareas de control sobre los objetos accedidos.

Implementación
Tenemos un objeto padre Asunto del que heredan otros dos:AsuntoReal y Proxy, todos ellos tienen un método petición(). El cliente llamaría al método petición() de Asunto, el cual pasaría la petición a Proxy, que a su vez instanciaría AsuntoReal y llamaría a su petición().
Esto nos permite controlar las peticiones a AsuntoReal mediante el Proxy, por ejemplo instanciando AsuntoReal cuando sea necesario y eliminándolo cuando deje de serlo.
Sistemas:
Un servidor proxy es un equipo intermediario situado entre el sistema del usuario e Internet. Puede utilizarse para registrar el uso de Internet y también para bloquear el acceso a una sede Web.
El servidor de seguridad del servidor proxy bloquea algunas redes o páginas Web por diversas razones. En consecuencia, es posible que no pueda descargar el entorno de ejecución de Java (JRE) o ejecutar algunos applets de Java.
Servidores proxy: Funcionan como servidor de seguridad y como filtro de contenidos. Son un mecanismo de seguridad implementado por el ISP o los administradores de la red en un entorno de Intranet para desactivar el acceso o filtrar las solicitudes de contenido para ciertas sedes Web consideradas ofensivas o dañinas para la red y los usuarios. Mejoran el rendimiento. Guardan en la memoria caché las páginas Web a las que acceden los sistemas de la red durante un cierto tiempo. Cuando un sistema solicita la misma página web, el servidor proxy utiliza la información guardada en la memoria caché en lugar de recuperarla del proveedor de contenidos. De esta forma, se accede con más rapidez a las páginas Web.

Código ejemplo
package com.autentia.adictos.proxy;

public interface Manager {
public void save(Object obj);
public void remove(Integer id);
} package com.autentia.adictos.proxy;

public class UserManagerImpl implements Manager {

public void save(Object obj) {
System.out.println("I save user Objects");
}

public void remove(Integer id) {
System.out.println("I remove user objects");
}

}package com.autentia.adictos.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class ManagerHandler implements InvocationHandler {

Manager realManager = null;

public ManagerHandler(Manager realManager) {
this.realManager = realManager;
}

/* Este es el método callback que será invocado previamente a cada método de los managers. */
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {

System.out.println("A Manager is being invoked:"+method.getName());

// Continuamos invocando al Manager real.
return method.invoke(realManager,args);
}

}package com.autentia.adictos.proxy;

import java.lang.reflect.Proxy;

public class FactoryManager {

public Manager createManager(Class claseManager) {

Manager realManager = null;

try {
// Creamos un objeto de la clase que recibimos.
realManager = (Manager)claseManager.newInstance();
} catch (Exception e) {
e.printStackTrace();
return null;
}

/* Creamos el CallBack Handler y le pasamos el objeto real para ser invocado posteriormente en su método invoke. */

ManagerHandler handler = new ManagerHandler(realManager);

// Creamos el proxy.
Class[] interfacesQueEncapsulo = new Class[] {Manager.class};
return (Manager)Proxy.newProxyInstance(
claseManager.getClassLoader(),
interfacesQueEncapsulo,handler);
}
}package com.autentia.adictos.proxy;

public class Test {

public static void main(String[] args) {
// Creamos ahora la factoria
FactoryManager factory = new FactoryManager();

// Usamos la factoria para crear un Proxy sobre UserManagerImpl
Manager manager = factory.createManager(UserManagerImpl.class);

Object obj = new Object();
// Invocamos a los métodos:
manager.save(obj);
manager.remove(1);

}

}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {

openTransaction();

Object obj = method.invoke(realManager,args);

closeTransaction();

return obj;
}


Usos conocidos


Patrones relacionados

Adapter: un adapter proporciona una interfaz frontal de un objeto especifico, de manera similar a como lo hace el patron Proxy. Sin embargo, el patron Proxy proporciona la misma interfaz para el objeto, y el patron Adapter proporciona una interfaz diferente.