Javaでのアダプターデザインパターン

アダプタデザインパターンは、構造的なデザインパターンの一つであり、2つの関係のないインタフェースを一緒に動作させるために使用されます。これらの関係のないインタフェースを結ぶオブジェクトはアダプタと呼ばれます。

アダプタデザインパターン

アダプタデザインパターンの素晴らしい実生活の例の一つは、携帯電話の充電器です。携帯電話のバッテリーは3ボルトで充電する必要がありますが、通常のコンセントは120V(米国)または240V(インド)を生成します。そのため、携帯電話の充電ソケットと壁のコンセントの間で充電器がアダプタの役割を果たします。このチュートリアルでは、アダプタデザインパターンを使用してマルチアダプタを実装しようとします。まず最初に、Volt(ボルトを測定するためのクラス)とSocket(定数120Vのボルトを生成するクラス)の2つのクラスを作成します。

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

今度は、3ボルト、12ボルト、デフォルトの120ボルトを生成できるアダプタを作成したいと思います。そのために、これらのメソッドを持つアダプタインタフェースを作成します。

package com.journaldev.design.adapter;

public interface SocketAdapter {

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

双方向アダプタパターン

Adapterパターンを実装する際には、クラスアダプタとオブジェクトアダプタの2つのアプローチがありますが、どちらのアプローチでも同じ結果が得られます。

  1. クラスアダプタ – この形式では、Javaの継承を使用し、ソースインターフェース(この場合はSocketクラス)を拡張します。
  2. オブジェクトアダプタ – この形式では、Javaのコンポジションを使用し、アダプタにソースオブジェクトが含まれます。

アダプタデザインパターン – クラスアダプタ

ここに、クラスアダプタアプローチのアダプタの実装例があります。

package com.journaldev.design.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);
	}

}

アダプタデザインパターン – オブジェクトアダプタの実装

ここに、オブジェクトアダプタのアダプタの実装例があります。

package com.journaldev.design.adapter;

public class SocketObjectAdapterImpl implements SocketAdapter{

	//アダプタパターンのためにコンポジションを使用
	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);
	}
}

アダプタの実装は、どちらもほぼ同じで、SocketAdapterインターフェースを実装しています。アダプタインターフェースは、抽象クラスにすることもできます。次は、アダプタデザインパターンの実装を消費するためのテストプログラムです。

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

上記のテストプログラムを実行すると、以下の出力が得られます。

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

アダプタデザインパターンのクラス図

JDKのアダプタデザインパターンの例

JDKクラスで見つけられるいくつかのアダプタデザインパターンの例は、

  • java.util.Arrays#asList()
  • java.io.InputStreamReader(InputStream)(Readerを返す)
  • java.io.OutputStreamWriter(OutputStream)(Writerを返す)

以上、Javaにおけるアダプタデザインパターンの説明でした。

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