La mejor forma de comenzar a comprender el patrón Adapter es presentar un símil con objetos de la vida real. Imaginemos que tenemos una lujosa y moderna tarjeta gráfica con salidas hdmi pero solo disponemos de una antigua pantalla con entrada VGA y  un cable hdmi. Es evidente que no podemos pasar información de un emisor digital a un receptor analógico, por lo que necesitamos algo capaz de traducir esa información entre ambos.

patron adapter uml

En este caso el adaptador se encargaría de transformar la salida digital en analógica haciendo la información accesible para el monitor VGA. Pongamos ahora un ejemplo de programación. Tenemos un conjunto de clases que representan objetos con una funcionalidad muy similar, por ejemplo aviones. Los distintos tipos de aviones heredan de una clase abstracta llamada Avión, tal y como se muestra en el siguiente UML:

patron adapter uml

Posteriormente creamos una clase Aeropuerto. Esta clase aeropuerto está pensada para almacenar aviones, por lo que creamos una lista de este tipo de objetos en uno de sus atributos. Pero unas semanas más tarde, nos damos cuenta de que ese aeropuerto no almacena solamente aviones, sino que también puede almacenar helicópteros… e incluso otro tipo de objetos como drones, o dirigibles.

patron adapter uml

En este momento nos planteamos las siguientes dos soluciones:

  • Hacer que Helicóptero herede de Avión.
  • Crear una interfaz (Aterrizable) para todos los objetos, hacer que la implementen tanto aviones como helicópteros y así poder almacenarlos en una lista del aeropuerto de tipo List.

La primera solución es un realmente mala. La clase abstracta Avion puede implementar métodos en el futuro incompatibles con los helicópteros, como por ejemplo desplegarFlaps() que no poseen un equivalente para los helicópteros, por lo que descartamos esta opción enseguida. La segunda opción, aunque deseable, no es posible en todos los casos. Por ejemplo, se puede dar el caso de que la clase forme parte de una API y/o no podamos modificar su código fuente. En ese caso tenemos que crear un adaptador que haga pensar que nuestros helicópteros son aviones. ¿Cómo hacemos esto?

  1. Creando una nueva clase que extienda de avión y que contenga un helicóptero
  2. Implementando los métodos de la clase abstracta de forma que se comporten como lo haría el helicóptero que lo contiene.

Siguiendo con el ejemplo del diagrama UML anterior y los dos pasos mencionados, la clase adaptadora nos quedaría de la siguiente forma:

Ahora la clase principal puede contener helicópteros siempre que estén contenido en un adaptador e incluso puede tratarlos como si fueran aviones, pero con el comportamiento de un helicóptero, de forma que cuando se llame a un metodo como aterrizar, la lógica de los mismos dependa del tipo de avion concreto o del adaptador de un objeto distinto. El diagrama UML final quedaría de la siguiente forma:

patron adapter uml

El patrón adapter es muy útil para situaciones en las que necesitemos gestionar distintas clases con comportamientos parecidos pero no podamos realizar cambios en el código fuente para abstraer una interfaz común a todas ellas. Por lo tanto, como ya mencionamos, puede ser muy útil para manejar cierta clase de APIs en nuestros programas.