Padrão de Design Adapter em Java

O padrão de design Adapter é um dos padrões de design estrutural e é usado para que duas interfaces não relacionadas possam trabalhar juntas. O objeto que une essas interfaces não relacionadas é chamado de Adapter.

Padrão de Design Adapter

Um ótimo exemplo real do padrão de design Adapter é o carregador de celular. A bateria do celular precisa de 3 volts para carregar, mas a tomada normal produz 120V (EUA) ou 240V (Índia). Então, o carregador de celular funciona como um adaptador entre a tomada de carregamento do celular e a tomada da parede. Tentaremos implementar um adaptador múltiplo usando o padrão de design Adapter neste tutorial. Então, primeiro de tudo teremos duas classes – Volt (para medir volts) e Socket (produzindo volts constantes de 120V).

package com.journaldev.design.adapter;

public class Volt {

	private int volts;
	
	public Volt(int v){
		this.volts=v;
	}

	public int getVolts() {
		return volts;
	}

	public void setVolts(int volts) {
		this.volts = volts;
	}
	
}
package com.journaldev.design.adapter;

public class Socket {

	public Volt getVolt(){
		return new Volt(120);
	}
}

Agora queremos construir um adaptador que possa produzir 3 volts, 12 volts e os 120 volts padrão. Então, primeiro de tudo, criaremos uma interface de adaptador com esses métodos.

package com.journaldev.design.adapter;

public interface SocketAdapter {

	public Volt get120Volt();
		
	public Volt get12Volt();
	
	public Volt get3Volt();
}

Padrão de Adaptador Bidirecional

Ao implementar o padrão Adaptador, existem duas abordagens – adaptador de classe e adaptador de objeto – no entanto, ambas essas abordagens produzem o mesmo resultado.

  1. Adaptador de Classe – Esta forma utiliza herança em Java e estende a interface de origem, no nosso caso a classe Socket.
  2. Adaptador de Objeto – Esta forma utiliza Composição em Java e o adaptador contém o objeto de origem.

Padrão de Projeto Adaptador – Adaptador de Classe

Aqui está a implementação da abordagem do adaptador de classe do nosso adaptador.

package com.journaldev.design.adapter;

//Usando herança para o padrão adaptador
public class SocketClassAdapterImpl extends Socket implements SocketAdapter{

	@Override
	public Volt get120Volt() {
		return getVolt();
	}

	@Override
	public Volt get12Volt() {
		Volt v= getVolt();
		return convertVolt(v,10);
	}

	@Override
	public Volt get3Volt() {
		Volt v= getVolt();
		return convertVolt(v,40);
	}
	
	private Volt convertVolt(Volt v, int i) {
		return new Volt(v.getVolts()/i);
	}

}

Padrão de Projeto Adaptador – Implementação do Adaptador de Objeto

Aqui está a implementação do adaptador de objeto do nosso adaptador.

package com.journaldev.design.adapter;

public class SocketObjectAdapterImpl implements SocketAdapter{

	//Usando Composição para o padrão adaptador
	private Socket sock = new Socket();
	
	@Override
	public Volt get120Volt() {
		return sock.getVolt();
	}

	@Override
	public Volt get12Volt() {
		Volt v= sock.getVolt();
		return convertVolt(v,10);
	}

	@Override
	public Volt get3Volt() {
		Volt v= sock.getVolt();
		return convertVolt(v,40);
	}
	
	private Volt convertVolt(Volt v, int i) {
		return new Volt(v.getVolts()/i);
	}
}

Repare que ambas as implementações do adaptador são quase iguais e implementam a interface SocketAdapter. A interface do adaptador também pode ser uma classe abstrata. Aqui está um programa de teste para consumir nossa implementação do padrão de projeto de adaptador.

package com.journaldev.design.test;

import com.journaldev.design.adapter.SocketAdapter;
import com.journaldev.design.adapter.SocketClassAdapterImpl;
import com.journaldev.design.adapter.SocketObjectAdapterImpl;
import com.journaldev.design.adapter.Volt;

public class AdapterPatternTest {

	public static void main(String[] args) {
		
		testClassAdapter();
		testObjectAdapter();
	}

	private static void testObjectAdapter() {
		SocketAdapter sockAdapter = new SocketObjectAdapterImpl();
		Volt v3 = getVolt(sockAdapter,3);
		Volt v12 = getVolt(sockAdapter,12);
		Volt v120 = getVolt(sockAdapter,120);
		System.out.println("v3 volts using Object Adapter="+v3.getVolts());
		System.out.println("v12 volts using Object Adapter="+v12.getVolts());
		System.out.println("v120 volts using Object Adapter="+v120.getVolts());
	}

	private static void testClassAdapter() {
		SocketAdapter sockAdapter = new SocketClassAdapterImpl();
		Volt v3 = getVolt(sockAdapter,3);
		Volt v12 = getVolt(sockAdapter,12);
		Volt v120 = getVolt(sockAdapter,120);
		System.out.println("v3 volts using Class Adapter="+v3.getVolts());
		System.out.println("v12 volts using Class Adapter="+v12.getVolts());
		System.out.println("v120 volts using Class Adapter="+v120.getVolts());
	}
	
	private static Volt getVolt(SocketAdapter sockAdapter, int i) {
		switch (i){
		case 3: return sockAdapter.get3Volt();
		case 12: return sockAdapter.get12Volt();
		case 120: return sockAdapter.get120Volt();
		default: return sockAdapter.get120Volt();
		}
	}
}

Quando executamos o programa de teste acima, obtemos a seguinte saída.

v3 volts using Class Adapter=3
v12 volts using Class Adapter=12
v120 volts using Class Adapter=120
v3 volts using Object Adapter=3
v12 volts using Object Adapter=12
v120 volts using Object Adapter=120

Diagrama de Classe do Padrão de Projeto do Adaptador

Exemplo do Padrão de Projeto do Adaptador no JDK

Alguns exemplos do padrão de projeto do adaptador que pude encontrar facilmente nas classes do JDK são;

  • java.util.Arrays#asList()
  • java.io.InputStreamReader(InputStream) (retorna um Reader)
  • java.io.OutputStreamWriter(OutputStream) (retorna um Writer)

Isso é tudo para o padrão de projeto do adaptador em Java.

Source:
https://www.digitalocean.com/community/tutorials/adapter-design-pattern-java