Adapter

Adapter
Información sobre la plantilla
Adapter-Object.jpg
Concepto:Técnica usada en programación para utilizar una clase que de otro modo, no podría ser utilizada.

Adapter. El patrón Adapter (adaptador en español), adapta una interfaz para que pueda ser utilizada por una clase que de otro modo no podría ser utilizada, es decir, reutiliza un componente ya existente que no es compatible. El patrón adaptador se utiliza para evitar la necesidad de cambiar el código cuando cambia una interfaz, o para permitir futuras modificaciones o implementaciones cuando diseña clases genéricas.


Tipo y propósito

Estructura, tanto a nivel de clases como a nivel de objetos.

Propósito

Convertir la interfaz de una clase para que se adapte a lo que el cliente que la usa necesita, permitiendo así que trabajen juntas las clases cuyas interfaces son incompatibles.


Participantes

  • Objetivo: Define la interfaz específica del dominio que usa el Cliente.
  • Cliente: Colabora con objetos que se ajustan a la interfaz Objetivo.
  • Adaptable: Define una interfaz existente que necesita ser adaptada.
  • Adaptador: Adapta la interfaz de Adaptable a la interfaz Objetivo.


Variaciones del patrón

  • Un adaptador y múltiples adaptables. Dependiendo del diseño del sistema el adaptador puede añadir funcionalidad a todos los Adaptables a la vez.
  • Adaptadores no basados en interfaz. Se da en las situaciones donde no se pueden utilizar interfaces, por ejemplo, si se reciben componentes completos que no implementan ninguna interfaz.
  • Una capa de interfaz entre el invocador y el adaptador, y otra entre el adaptador y el adaptable. La capa entre el invocador y el adaptador permite que se puedan introducir fácilmente nuevos adaptadores en el sistema en tiempo de ejecución. Y entre el adaptador y el adaptable, hace que los adaptables sean cargados dinámicamente en tiempo de ejecución.


Componentes de un Adapter

Un Adapter tiene dos componentes esenciales:

  • Primero, necesitamos una clase que defina la interfaz que tiene que ser adaptada, el "adaptado".
  • Segundo, necesitamos la clase "adaptador" que defina la interfaz esperada y haga corresponder los métodos de la interfaz con aquellos definidos por el adaptador. El cliente llama a uno de los métodos "esperados" que están expuestos en un lado del adaptador, el que simplemente pasa la llamada al método apropiado en el adaptado.


Implementación de un adaptador

Un adaptador es típicamente implementado utilizando herencia múltiple, al crear una subclase del adaptador que herede los métodos privados y, permitiendo que herede además, la interfaz pública de las clases que definen la interfaz requerida.


Se puede utilizar cuando

  • Cuando se quiere usar una clase ya existente, pero su interfaz no encaja con lo que se necesita.
  • Cuando se quiere crear una clase reutilizable, para cooperar con otras clases que no tengan, necesaria ni previsiblemente, interfaces compatibles.
  • (Sólo en la versión para objetos). Cuando se quieren usar varias subclases ya existentes, pero no resulta práctico adaptarlas una a una mediante herencia. En vez de esto, se puede adaptar la interfaz de la clase de la cual todas ellas heredan (y especializan) su comportamiento.


Ventajas e inconvenientes

Ventajas

A nivel de clases...

  • Facilidad para redefinir el comportamiento de la clase adaptada.
  • Simplicidad (un sólo objeto, no hay punteros ni indirecciones adicionales).

A nivel de objetos...

  • Flexibilidad para que un sólo adaptador trabaje con muchas clases a adaptar (en concreto, puede hacerlo con toda una jerarquía de clases).
  • Extensibilidad, puesto que se pueden añadir funcionalidades a todas las clases adaptadas a la vez.

Inconvenientes

A nivel de clases...

  • Inflexibilidad, puesto que un sólo adaptador no puede trabajar con una clase y sus hijos a la vez.

A nivel de objetos...

  • Dificultad para redefinir el comportamiento de la clase adaptada.


Consecuencias de su utilización

El cliente es independiente de las clases finales que utiliza. Es posible utilizar la clase Adaptador para monitorizar que clases llaman a qué métodos de las clases finales. Adaptador de Clase:

  • La clase adaptadora puede redefinir y ampliar la interfaz de la clase adaptada.
  • La clase adaptadora adapta una clase adaptable a objetivo, pero se refiere únicamente a una clase Adaptable concreta, por lo tanto no nos servirá para todas sus subclases.

Adaptador de Objeto:

  • Permite que un mismo Adaptador funcione con muchos Adaptables.
  • La clase adaptadora puede utilizar todas las subclases de la clase adaptada, ya que tiene constancia de los objetos que instancia.
  • Hace que sea más difícil redefinir el comportamiento de Adaptable. Se necesitará crear una subclase de Adaptable y hacer que el adaptador se refiera a la subclase en vez de a la clase adaptable en sí.

Patrones relacionados

  • Bridge: Aunque son parecidos tienen objetivos diferentes ya que Bridge está pensado para separar una interfaz de su implementación, mientras que Adapter cambia la interfaz de un objeto existente.
  • Decorator: Adapter modifica la interfaz de un objeto, pero mantiene su funcionalidad, Decorator permite que la interfaz sea igual pero mejora su funcionalidad.
  • Facade: Es una alternativa a Adaptador cuando en lugar de llamar a un solo objeto se necesita llamar a varios.
  • Proxy: Es similar a Adaptador en el sentido en que proporcionan una interfaz, con la diferencia en que Proxy ofrece la misma interfaz que la clase a la que se llama.


Otros aspectos de interés

  • En el adaptador a nivel de clase, el "adaptador" hereda públicamente la interfaz de "objetivo" y privadamente la implementación de la "clase a adaptar".
  • Un "adaptador enchufable" es una clase que tiene ya definidas internamente las posibles adaptaciones de su interfaz.
  • Los "adaptadores de doble sentido" sirven para obtener transparencia ante diferentes clientes.
  • El adaptador a nivel de objeto requiere un poco más de esfuerzo que el adaptador a nivel de clase, pero a la larga, resulta más flexible.


Ejemplo de aplicación

En un editor gráfico de figuras lo fundamental es tener una abstracción que represente la forma de cualquier elemento gráfico genérico. Para conformar elementos ya existentes, nuevos o excesivamente complejos con la interfaz definida, para esta forma genérica podemos usar un adaptador (en este caso, a nivel de objetos).


Fuentes

  • Patrones del "Gang of Four". Unidad Docente de Ingeniería del Software Facultad de informática - Universidad Politécnica de Madrid.
  • Erich Gamma, Richard Helm, Ralph Johnson y John Vlissides. Design Patterns, Elements of Reusable Object-Oriented Software.
  • Portalfox