Qué es el patron de diseño Adapter

Qué es el patron de diseño Adapter

Siguiendo nuestro curso de programación hoy veremos el patrón Adapter. El patrón estructural Adapter permite convertir la interfaz de una clase en otra que es la que esperan los clientes. Permite que trabajen juntas clases que de otro modo no podrían por tener interfaces incompatibles. También es conocido como Wrapper (envoltorio).

uml_adapter

Aplicaciones

El patrón Adapter se puede aplicar cuando:

  • Queremos usar una clase existente, y ésta no tiene la interfaz que necesitamos.
  • Queremos crear una clase reutilizable que coopere con clases con las que no está relacionada. Por tanto, que no tendrán interfaces compatibles.
  • (Sólo la versión de objetos) Necesitamos usar varias subclases existentes pero sin tener que adaptar su interfaz creando una nueva subclase de cada una. Un adaptador de objetos puede adaptar la interfaz de su clase padre.

Ejemplo

Supongamos que estamos haciendo un editor de dibujo. La abstracción fundamental es el objeto gráfico (Shape), que puede dibujarse a sí mismo. Define una subclase para cada tipo de objeto gráfico: LineShape, PolygonShape…

Supongamos que, para implementar una subclase TextShape (bastante más compleja que las anteriores) queremos echar mano de una clase TextView que nos proporciona la biblioteca gráfica. Tenemos que tener claro que la interfaz TextView no tendrá nada que ver con la de Shape. Una opción sería cambiar la clase TextView para que implemente dicha interfaz pero normalmente esto no es una opción pues normalmente no tenemos acceso al código fuente. La idea es crear una clase TextShape que adapte la interfaz de TextView a la de Shape. Tenemos dos opciones:

  • Versión de clases: heredando la interfaz de Shape y la implementación de TextView.
  • Versión de objetos: mediante composición de objetos, haciendo que TextShape delegue en una instancia de TextView.

Nosotros nos quedaremos con la versión de objetos, pues al principio de este tutorial comentamos que siempre debemos priorizar en la composición de objetos en decremento de la herencia.

Versión de objetos

ejemplo_adapter_version_objetos

Código del ejemplo

public class Cliente {public static void main(String[] args) {    Forma linea = new Linea();    Forma rombo = new Rombo();    Forma texto = new CuadroTexto();    ArrayList<Forma> l = new ArrayList<Forma>();    l.add(linea);    l.add(rombo);    l.add(texto);    for (Forma f : l)        f.dibuja();}}public abstract class Forma {abstract void dibuja();}public class Linea extends Forma{@Overridevoid dibuja() {    System.out.println("----------------------");}}public class Rombo extends Forma {@Overridevoid dibuja() {    System.out.println("    *    ");    System.out.println("   ***   ");    System.out.println("  *****  ");    System.out.println(" ******* ");    System.out.println("  *****  ");    System.out.println("   ***   ");    System.out.println("    *    ");}}import javax.swing.JTextPane;// es más complicada y necesita usar una libreria externa TextViewpublic class CuadroTexto extends Forma{public JTextPane text = new JTextPane();void dibuja() {    text.setText("text");    System.out.println(text.getText());}}

Estructura general

estructura_patron_state_general

Versión de clases o de objetos

Además de que tenemos que priorizar la composición de objetos frente a la herencia la versión de objetos:

  • Permite que un único adaptador funcione no sólo como objeto de la clase adaptada, sino de cualquiera de sus subclases.
  • No es del tipo del objeto adaptado.

Por contra, la versión de clases permite:

  • Adaptar una clase concreta a una interfaz.
  • Introduce un solo objeto adicional, sin indirección.
  • Permite que el adaptador redefina el comportamiento de la clase adaptada.

Como siempre os aquí dejo el código final.

Para ti
Queremos saber tu opinión. ¡Comenta!