Javaにおけるアダプターデザインパターン。
アダプター・デザインパターンは、構造デザインパターンの一つであり、無関係な二つのインターフェースを連携させるために使用されます。これらの無関係なインターフェースを結ぶオブジェクトをアダプターと呼びます。
アダプターデザインパターン
アダプタデザインパターンの素晴らしい現実の例の一つは、モバイルチャージャーです。モバイルバッテリーは3ボルトの充電を必要としますが、通常のコンセントはアメリカでは120V、インドでは240Vを生み出します。そのため、モバイルチャージャーはモバイルの充電ソケットと壁コンセントの間でアダプタとして機能します。このチュートリアルでは、アダプタデザインパターンを使用してマルチアダプタを実装しようとします。まず、ボルト(ボルトを計測するためのクラス)とソケット(120Vの一定のボルトを生成するクラス)の2つのクラスが必要です。
package com.scdev.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.scdev.design.adapter;
public class Socket {
public Volt getVolt(){
return new Volt(120);
}
}
今、3ボルト、12ボルト、そしてデフォルトの120ボルトを出力できるアダプターを作りたいと考えています。そのために、まずこれらのメソッドを持つアダプターインターフェースを作成します。
package com.scdev.design.adapter;
public interface SocketAdapter {
public Volt get120Volt();
public Volt get12Volt();
public Volt get3Volt();
}
2通りのアダプターパターン
Adapterパターンを実装する際には、クラスアダプターとオブジェクトアダプターの2つのアプローチがありますが、どちらのアプローチでも同じ結果が得られます。
-
- クラスアダプター – この形式は、Javaの継承を使用し、ソースインターフェース(この場合はSocketクラス)を拡張します。
- オブジェクトアダプター – この形式は、Javaのコンポジションを使用し、アダプターはソースオブジェクトを含んでいます。
アダプター デザイン パターン – クラス アダプター
私たちのアダプターのクラスアダプターアプローチの実装は、こちらです。
package com.scdev.design.adapter;
//Using inheritance for adapter pattern
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.scdev.design.adapter;
public class SocketObjectAdapterImpl implements SocketAdapter{
//Using Composition for adapter pattern
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);
}
}
アダプタの実装が2つあり、どちらもほぼ同様であり、SocketAdapterインターフェースを実装しています。アダプタインターフェースは抽象クラスの場合もあります。以下は、私たちのアダプタデザインパターンの実装を消費するためのテストプログラムです。
package com.scdev.design.test;
import com.scdev.design.adapter.SocketAdapter;
import com.scdev.design.adapter.SocketClassAdapterImpl;
import com.scdev.design.adapter.SocketObjectAdapterImpl;
import com.scdev.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) (returns a Reader)
- java.io.OutputStreamWriter(OutputStream) (returns a Writer)
Javaにおけるアダプターデザインパターンについては以上です。