Adapter-Entwurfsmuster in Java

Adapter-Entwurfsmuster ist eines der strukturierten Entwurfsmuster und wird verwendet, damit zwei nicht verwandte Schnittstellen zusammenarbeiten können. Das Objekt, das diese nicht verwandten Schnittstellen verbindet, wird als Adapter bezeichnet.

Adapter-Entwurfsmuster

Ein großartiges Beispiel für das Adapter-Entwurfsmuster im wirklichen Leben ist das Handy-Ladegerät. Der mobile Akku benötigt 3 Volt zum Laden, aber die normale Steckdose liefert entweder 120 V (USA) oder 240 V (Indien). Das Handy-Ladegerät fungiert daher als Adapter zwischen der mobilen Ladebuchse und der Wandsteckdose. In diesem Tutorial werden wir versuchen, einen Mehrfachadapter mit dem Adapter-Entwurfsmuster zu implementieren. Dazu werden wir zunächst zwei Klassen erstellen – Volt (zum Messen von Volt) und Socket (erzeugt konstante Volt von 120 V).

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);
	}
}

Jetzt möchten wir einen Adapter erstellen, der 3 Volt, 12 Volt und standardmäßig 120 Volt erzeugen kann. Dazu erstellen wir zunächst eine Adapter-Schnittstelle mit diesen Methoden.

package com.journaldev.design.adapter;

public interface SocketAdapter {

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

Zweiseitiges Adaptermuster

Während der Implementierung des Adapter-Musters gibt es zwei Ansätze – den Klassenadapter und den Objektadapter – jedoch erzeugen beide Ansätze dasselbe Ergebnis.

  1. Klassenadapter – Diese Form verwendet Java-Vererbung und erweitert die Quellschnittstelle, in unserem Fall die Socket-Klasse.
  2. Objektadapter – Diese Form verwendet Java-Komposition und der Adapter enthält das Quellobjekt.

Adapter-Designmuster – Klassenadapter

Hier ist die Implementierung des Klassenadapters für unseren Adapter.

package com.journaldev.design.adapter;

// Verwendung von Vererbung für das Adaptermuster
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);
	}

}

Adapter-Designmuster – Implementierung des Objektadapters

Hier ist die Implementierung des Objektadapters für unseren Adapter.

package com.journaldev.design.adapter;

public class SocketObjectAdapterImpl implements SocketAdapter{

	// Verwendung von Komposition für das Adaptermuster
	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);
	}
}

Beachten Sie, dass beide Adapterimplementierungen fast identisch sind und das SocketAdapter-Interface implementieren. Das Adapter-Interface kann auch eine abstrakte Klasse sein. Hier ist ein Testprogramm zur Verwendung unserer Adapter-Designmusterimplementierung.

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();
		}
	}
}

Wenn wir das obige Testprogramm ausführen, erhalten wir folgende Ausgabe.

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

Adapter Design Pattern Klassendiagramm

Adapter Design Pattern Beispiel in JDK

Einige Beispiele für das Adapter-Designmuster, die ich leicht in JDK-Klassen finden konnte, sind;

  • java.util.Arrays#asList()
  • java.io.InputStreamReader(InputStream) (gibt einen Reader zurück)
  • java.io.OutputStreamWriter(OutputStream) (gibt einen Writer zurück)

Das ist alles zum Adapter-Designmuster in Java.

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