Clasificación:
Patrón
Estructural.
Propósito:
Convertir la interfase de una clase en otra interfase
que el cliente espera. El adapter permite que clases trabajen juntas,
mediante la sobreescritura de los métodos de las clases padre e implementada
por el objeto adaptado, que de otra manera no podrian por las interfaces incompatibles.
También conocido como:
Wrapper.
Intención:
Se utiliza
para transformar una interfaz en otra, de tal modo que una clase que no pudiera
utilizar la primera, haga uso de ella a través de la segunda. Convierte la
interfaz de una clase en otra interfaz que el cliente espera. Adapter permite
a las clases trabajar juntas, lo que de otra manera no podrían hacerlo debido a
sus interfaces incompatibles
Motivación :
Este patrón se centra en resolver incompatibilidades
entre dos interfaces existentes. Se utiliza para hacer funcionar las cosas
después de que estas han sido diseñadas.
Aplicabilidad:
Se utiliza el patrón Adapter cuando se desea utilizar una
clase existente, y su interfaz no coincide con una que usted
necesita. Debe crear una clase reutilizable que coopere con o sin
relación de clases, es decir, clases que no tienen
necesariamente interfaces compatibles .
Estructura :
La
estructura de un class Adapter usa herencia de una
clase, e implementación de una interfaz para adaptar un objeto que posea características
de ambos.
Participantes:
El Cliente llama a las
operaciones en la instancia del Adapter. Luego, el Adapter llama
alAdaptee (el Adaptado) y lleva a cabo las operaciones pedidas
Object Adapter:
El object adapter adapta las clases, no
instancias u objetos. Esto puede traer problemas a la hora de instanciar esas
clases adaptadas ya que puede ocurrir que el objeto que se tiene no sea
lo que se necesita. En caso de que se necesite, ha de saberse que objetos
hay que adaptar cuando son llamados por el cliente, o mejor dicho
cuando ni bien se realice la “adaptación” se puede usar una pequeña
variante del Adapter, llamado Object Adapter
El object adapter trabaja creando una
clase Adapter que solamente implemente la interfaz y contiene una
instancia de la clase, o sea, un objeto a adaptar. No es necesario heredar la
clase a adaptar porque en realidad se va a trabajar con una instancia de
esta.
Cuándo
emplearlo:
· Se
quiere usar una clase existente, y su interfaz no concuerda con la que se
necesita.
·
Se quiere crear una clase reusable que coopere con clases no relacionadas
o imprevistas, esto es, clases que no tienen interfases compatibles
necesariamente.
·
(object adapter solamente) necesita usar varias subclases
existentes, pero no es practico adaptar sus interfases haciendo “subclassing”
por cada una. Un object adapter puede adaptar la interfaz de sus
clase padre (parent).
Consecuencias
:
Class
Adapter
· Adapta
el Adaptee al Target informando a un
class Adapter concreto. Comoconsecuencia, un
class Adapter no funciona cuando se quiere adaptar una clase y todas
sus subclases (subclassing).
·
El Adapter sobreescribe el comportamiento
del Adaptee ya que el Adapter es una subclase
del Adapteee .
·
Introduce solamente un objeto y no hay un puntero
adicional para conseguir el Adaptee.
Object Adapter
·
Un Adapter puede trabajar con
multiples Adaptees, esto es, el Adaptee en si y todas sus
subclases.
·
Hace más dificil de sobreescribir el comportamiento
del Adpatee. Requerirá hacer subclasssing del Adaptee y hacer
que el Adapter se remita a las subclases en vez delAdaptee en
si.
Implementación
:
El siguiente
ejemplo ilustra el patrón Adapter, el ejemplo trata de una tienda
de tortas, donde el usuario puede elegir una torta normal y/o agregarle algunas
especificaciones disponibles, como lo son diferentes sabores de cubiertas para
la decoración.
Creamos la
interfaz que permite adicionar características adicionales al objeto.
package logica;
//es nuestra clase Adaptee//
public interface Adaptee
{ //*la interfaz Adaptee permite adicionar a la
torta
public void decorar(); //
diferentes características *//
public voidcubiertaFresa();
public voidcubiertaNaranja();
public voidcubiertaCaramelo();
public voidcubiertaChocolate();
}
Ahora la
clase que adapta el objeto al la interfaz; permitiendo combinar las
características de ambas.
package logica;
//nuestra
clase Adapter//
public class Adapter extendsTorta implements Adaptee{
//*esta clase es la
adaptadora, donde el objeto creado
//hereda de torta y puede tener
caracteriaticas
// especiales dadas por la interfaz
Adaptee*//
String Cubierta;
String FiguraEspecial;
public Adapter(){
//constructor de la clase//
Cubierta="Sin
Cubierta";
FiguraEspecial="";
}
//obtiene
un String con el nombre del sabor de la cubierta//
public String
getCubierta(){
return this.Cubierta;
}
//obtiene un String que dice si el objeto posee una figura
decorativa//
public String getDecoracion(){
returnthis.FiguraEspecial;
}
@Override
// metodo de
la interfaz; asigna el nombre del sabor de la cubierta//
public voidcubiertaChocolate()
{
Cubierta="Con
Cubierta de Chocolate";
}
@Override
public voidcubiertaFresa()
{
Cubierta="Con
Cubierta de Fresa";
}
@Override
public voidcubiertaNaranja()
{
Cubierta="Con
Cubierta de Naranja";
}
@Override
public voidcubiertaCaramelo()
{
Cubierta="Con
Cubierta de
Caramelo";
}
@Override
//es un
metodo de la interfaz//
public void decorar()
{
//asigna una
figura decorativa al objeto//
FiguraEspecial="Decorada
Con Figura Especial";
}
@Override
//retorna la
descripcion la cubierta de la torta//
public String pedidoCubierta(){
return "Su
pedido esta listo: **TORTA **\n"+this.getCubierta();
}
@Override
//retorna la
descripcion de la decoración//
public String pedidoDecoracion() {
returnthis.getDecoracion();
}
}
Esta es la
clase principal la cual debe ser abstracta, permitiendo de este modo tener
métodos abstractos, que serán comunes simpre a cualquier pedido.
package logica;
//nuestra
clase Target//
//*clase principal a la que siempre pertenecerá el objeto creado la cual
posee metodos abstractos//
public abstract class Torta
{
public abstract String
pedidoCubierta();
public abstract String
pedidoDecoracion();
}
Por último,
creamos la interfaz la cual presenta una ventana que permite al cliente elegir
las características de la torta.
package intefaz;
import logica.*;
import java.awt.event.*;
import javax.swing.*;
//interfaz para la toma del pedido//
public class OrdenPasteleria extends JFrame implements ActionListener {
Adapter
torta;
private
JButton figuraDecorativa;
private
JButton cubiertaFresa;
private
JButton cubiertaCaramelo;
private
JButton cubiertaChocolate;
private
JButton cubiertaNaranja;
private
JTextArea suOrden;
private JLabel orden;
//constructor: inicializa y
localizan los atributos//
public
OrdenPasteleria(){
this.setSize(400,300);
this.setLayout(null);
this.setDefaultCloseOperation(OrdenPasteleria.DISPOSE_ON_CLOSE);
this.setTitle(":;;Pasteleria UD:::");
torta= new
Adapter();
orden = new JLabel();
orden.setSize(350,20);
orden.setLocation(20,
20);
orden.setText("Seleccione las
características de su Torta ");
this.getContentPane().add(orden);
suOrden = new JTextArea();
suOrden.setSize(350,50);
suOrden.setLocation(20, 200);
suOrden.setText("Usted tiene una Torta
" + torta.getCubierta());
this.getContentPane().add(suOrden);
suOrden.setEditable(false);
figuraDecorativa = new JButton();
figuraDecorativa.setSize(150,
25);
figuraDecorativa.setLocation(100, 150);
figuraDecorativa.setText("Figura Especial");
this.getContentPane().add(figuraDecorativa);
figuraDecorativa.addActionListener(this);
cubiertaFresa = new JButton();
cubiertaFresa.setSize(170, 30);
cubiertaFresa.setLocation(20, 50);
cubiertaFresa.setText("Cubierta de
Fresa");
this.getContentPane().add(cubiertaFresa);
cubiertaFresa.addActionListener(this);
cubiertaCaramelo = new JButton();
cubiertaCaramelo.setSize(170, 30);
cubiertaCaramelo.setLocation(200, 50);
cubiertaCaramelo.setText("Cubierta de
Caramelo");
this.getContentPane().add(cubiertaCaramelo);
cubiertaCaramelo.addActionListener(this);
cubiertaChocolate = new JButton();
cubiertaChocolate.setSize(170, 30);
cubiertaChocolate.setLocation(20, 100);
cubiertaChocolate.setText("Cubierta de
Chocolate");
this.getContentPane().add(cubiertaChocolate);
cubiertaChocolate.addActionListener(this);
cubiertaNaranja = new JButton();
cubiertaNaranja.setSize(170, 30);
cubiertaNaranja.setLocation(200, 100);
cubiertaNaranja.setText("Cubierta de
Naranja");
this.getContentPane().add(cubiertaNaranja);
cubiertaNaranja.addActionListener(this);
}
@Override
//modifica el objeto
a peticion del cliente//
public void actionPerformed(ActionEvent e)
{
if (e.getSource() ==
figuraDecorativa) {
torta.decorar();
}
if (e.getSource() == cubiertaFresa){
torta.cubiertaFresa();
}
if (e.getSource() == cubiertaCaramelo) {
torta.cubiertaCaramelo();
}
if (e.getSource() == cubiertaChocolate) {
torta.cubiertaChocolate();
}
if
(e.getSource() == cubiertaNaranja) {
torta.cubiertaNaranja();
}
suOrden.setSize(350,50);
suOrden.setLocation(20, 200);
//muestra el pedido como tal, las características de la torta//
suOrden.setText(torta.pedidoCubierta()+'\n'+torta.pedidoDecoracion());
}
}
Usos conocidos:
Clases
adaptadoras del JDK
- Para gestionar eventos un objeto debe implementar EventListener
- Para gestionar eventos de objetos de tipo Windowdebe implementar la interfaz WindowListenerque extiende EventListener
- WindowListenertiene siete métodos, pero en muchas ocasiones sólo no se usan más de tres.
- El JDK proporciona la clase abstracta WindowAdapterpara dicho fin.
Patrones
relacionados :
· Bridge
: Tiene una estructura similar alAdapter, pero un intento
diferente : Su proposito es separar la interfase de su implementación asi esta
puede variar facilmente y de forma independiente. El proposito del Adapter es
el cambio de interfase de un objeto existente.
· Decorator
: Agrega resonsabilidades a un objeto dinamicamente sin cambiar su
interfase .
Un Decorator en cambio es mas transparente a la aplicación
que un Adapter, como consecuencia
Soporta composición recursiva, lo cual no es posible con el
patronAdapter.
· Proxy : Define
un lugar para otro objeto para controlar el acceso y no cambia su interfase.
REFERENCIAS:
|
Design Patterns: Elements of
Reusable Object-Oriented Software
Gamma, Helm, Johnson,
Vlissides
Editorial Addison-Wesley
|
No hay comentarios:
Publicar un comentario