Modello di Progettazione dell’Adattatore in Java

Il pattern di progettazione dell’adattatore è uno dei pattern di progettazione strutturali ed è utilizzato affinché due interfacce non correlate possano lavorare insieme. L’oggetto che unisce queste interfacce non correlate è chiamato Adattatore.

Pattern di progettazione dell’Adattatore

Un ottimo esempio pratico del pattern di progettazione dell’Adattatore è il caricatore per cellulari. La batteria del cellulare ha bisogno di 3 volt per caricarsi, ma la presa normale produce 120V (negli Stati Uniti) o 240V (in India). Quindi il caricatore per cellulari funziona come un adattatore tra la presa di ricarica del cellulare e la presa a muro. Cercheremo di implementare un adattatore multiuso utilizzando il pattern di progettazione dell’Adattatore in questo tutorial. Per prima cosa, creeremo due classi – Volt (per misurare i volt) e Socket (che produce costantemente 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);
	}
}

Ora vogliamo creare un adattatore che possa produrre 3 volt, 12 volt e i 120 volt predefiniti. Pertanto, creeremo prima un’interfaccia per l’adattatore con questi metodi.

package com.journaldev.design.adapter;

public interface SocketAdapter {

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

Pattern di progettazione dell’Adattatore bidirezionale

Durante l’implementazione del pattern Adapter, ci sono due approcci – adapter di classe e adapter di oggetto – tuttavia entrambi questi approcci producono lo stesso risultato.

  1. Adapter di Classe – Questa forma utilizza l’ereditarietà java ed estende l’interfaccia di origine, nel nostro caso la classe Socket.
  2. Adapter di Oggetto – Questa forma utilizza la composizione Java e l’adattatore contiene l’oggetto di origine.

Pattern di Progettazione Adapter – Adapter di Classe

Ecco l’implementazione dell’approccio adapter di classe del nostro adattatore.

package com.journaldev.design.adapter;

//Utilizzo dell'ereditarietà per il pattern adapter
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);
	}

}

Pattern di Progettazione Adapter – Implementazione Adapter di Oggetto

Ecco l’implementazione dell’approccio adapter di oggetto del nostro adattatore.

package com.journaldev.design.adapter;

public class SocketObjectAdapterImpl implements SocketAdapter{

	//Utilizzo della composizione per il pattern adapter
	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);
	}
}

Si noti che entrambe le implementazioni dell’adattatore sono quasi identiche e implementano l’interfaccia SocketAdapter. L’interfaccia dell’adattatore può anche essere una classe astratta. Ecco un programma di test per consumare la nostra implementazione del pattern di progettazione dell’adattatore.

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 eseguiamo il programma di test sopra, otteniamo il seguente output.

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

Diagramma delle Classi del Pattern di Progettazione dell’Adattatore

Esempio del Pattern di Progettazione dell’Adattatore in JDK

Alcuni degli esempi del pattern di progettazione dell’adattatore che ho potuto trovare facilmente nelle classi JDK sono;

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

E questo è tutto per il pattern di progettazione dell’adattatore in Java.

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