Cidenet+Blog+Desarrollo limpio+Adapter

Adapter

¿Qué es?, ¿Qué problema resuelve?

El patrón Adapter se utiliza para convertir una interfaz de una clase, en otra que el cliente espera. Adapter permite que dos clases que son incompatibles entre sí debido a incompatibilidad de interfaces, puedan trabajar juntas.

Este patrón es útil cuando:

  • Se necesita utilizar una clase existente y su interfaz no es compatible con la interfaz implementada en la clase donde se desea utilizar tal clase existente. 
  • Cuando ya se cuenta con un sistema y es necesario agregarle nuevas características. Adapter permite hacer esto de una forma limpia, ya que el código existente no se modifica.
  • Se desea crear una clase reusable que coopera con clases que no necesariamente tienen interfaces compatibles.

Diagrama

Imagen 1

  • Target: Define la interfaz que el cliente utiliza.
  • Client: Provee los objetos de acuerdo a la interfaz Target.
  • Adaptee: Define una interfaz existente que necesita ser adaptada.
  • Adapter: Adapta la interfaz Adaptee a la interfaz Target.

Un buen ejemplo de este patrón son los conectores de la energía. Suponga que viaja a Europa. Allí los tomacorrientes son diferentes a los colombianos. El problema es que el tomacorriente no se puede cambiar. La solución es comprar un adaptador que se ajuste al conector de Colombia y que a la vez se pueda conectar al tomacorriente europeo.

En este caso el Target es el conector colombiano, Client es la persona dueña del conector, quien necesita utilizar el tomacorriente. Adaptee sería el tomacorriente europeo que no se puede cambiar y Adapter sería el adaptador que actúa de puente entre el conector colombiano y el tomacorriente europeo; y permite al cliente tener acceso a electricidad.

Ejemplo

Suponga que existe una aplicación que se conecta a un servicio de terceros y que este servicio, en su API, establece que solo se permiten cuerpos de peticiones en formato XML. Inicialmente se realiza la implementación y se hacen las peticiones con el correspondiente formato XML. Nótese que ExternalSDKLibrary es una clase que provee el SDK del tercero y por ende, no se puede modificar.

@Test
public void shouldNotNeedAnAdapterOnXmlRequestBody() {
	Request request = new Request("<?xml>...");
	assertTrue(new ExternalSDKLibrary(request.getMessage()).makeRequest());
}

Pero pasado el tiempo, la aplicación necesita recibir peticiones en formato JSON, sin embargo, el SDK aún no permite hacer peticiones con tal formato. En esta situación se puede crear un adaptador que convierta la petición JSON a XML para posteriormente hacer la petición por medio del SDK del tercero.

Para ello, se crea una interfaz que representa los métodos necesarios para que el adaptador establezca la comunicación entre la petición JSON y la petición esperada por el tercero.

public interface JSONToXMLAdapter {
	boolean makeRequest();

}

Estas validaciones repetidas se pueden evitar haciendo uso de prototipos. Para esto, en esta clase también se implementa el método clone, el cual llama al constructor padre para que se realice la copia campo a campo de un objeto a otro.

@Override
public Notification clone() throws CloneNotSupportedException {
   return ((Notification) super.clone());
}

Luego, se crea el adaptador como tal, el cual debe implementar la interfaz anteriormente presentada. Este adaptador debe contener como atributo un objeto de la clase cliente. En este caso esta clase contiene la petición en formato JSON. Esta clase es la que no es compatible con el SDK.

En el método implementado makeRequest, se convierte la respuesta JSON de la clase request a XML por medio del método ConvertToXML. Teniendo esta conversión hecha, ya se puede llamar correctamente al método del SDK del tercero como se presenta en la imagen 4.

public class JSonToXMLAdapterImpl implements JSONToXMLAdapter {
	private final Request request;


	public JSonToXMLAdapterImpl(Request request) {
		this.request = request;
	}


	public boolean makeRequest() {
		ExternalSDKLibrary externalSDKLibrary = convertToXML();
		return externalSDKLibrary.makeRequest();
	}


	private ExternalSDKLibrary convertToXML() {
		return new ExternalSDKLibrary("<?xml>" + request.getMessage());

	}

}

De este modo se puede hacer uso del SDK, a pesar de que inicialmente se están recibiendo peticiones en formato JSON.

@Test

public void ShouldNeedAnAdapterOnJSONRequestBody() {
	JSonToXMLAdapterImpl jSonToXMLAdapter = 
	       new JSonToXMLAdapterImpl(new Request("{"campo": "valor"}"));
	assertTrue(jSonToXMLAdapter.makeRequest());
}

En caso de que se requieran recibir peticiones en otro formato por parte del cliente, únicamente es necesario crear un nuevo adaptador para ese nuevo tipo de formato.

Nótese que la utilidad de Adapter radica en poder utilizar una interfaz no compatible que no se puede modificar, bien sea porque el código es ajeno al sistema o porque el código hace parte del sistema, pero su modificación implicaría cambios significativos en otros lugares de la aplicación, o bien, porque es una aplicación legada.

El ejemplo completo se encuentra en https://bit.ly/3i4xtFC

Conclusiones

  • Una ventaja del patrón Adapter es que no se necesita cambiar la interfaz existente, evitando cambios en el código existente, asegurando que no se generen efectos colaterales en otros componentes de la aplicación.
  • Adapter hace funcionar las cosas después de haber sido diseñadas. por ejemplo, en casos donde el diseño inicial no fue óptimo.
  • Es útil cuando se está realizando una migración de una aplicación legada y aún existen módulos en esta que son necesarios porque no se han migrado.
  • Ayuda a reutilizar código.

Fuentes

Contáctanos

Déjanos tus datos

    Medellín - Colombia

  • Calle 47D #72-29
  • (+57) 4 3222567
  • comunicaciones@cidenet.com.co

    Estados Unidos

  • 1200 Colorado Blvd, Denver Colorado 80220
  • (+1) 7723619239
  • jceballos@cidenet.net
WhatsApp
>