웹사이트 검색

Java의 어댑터 디자인 패턴


어댑터 디자인 패턴은 구조적 디자인 패턴 중 하나로 서로 관련이 없는 두 개의 인터페이스가 함께 동작할 수 있도록 사용된다. 이러한 관련 없는 인터페이스를 연결하는 개체를 어댑터라고 합니다.

어댑터 디자인 패턴

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

양방향 어댑터 패턴

어댑터 패턴을 구현하는 동안 클래스 어댑터와 개체 어댑터의 두 가지 접근 방식이 있지만 두 접근 방식 모두 동일한 결과를 생성합니다.

  1. 클래스 어댑터 - 이 양식은 자바 상속을 사용하고 소스 인터페이스(우리의 경우 소켓 클래스)를 확장합니다.
  2. 개체 어댑터 - 이 양식은 Java 컴포지션을 사용하며 어댑터에는 소스 개체가 포함됩니다.

어댑터 디자인 패턴 - 클래스 어댑터

다음은 어댑터의 클래스 어댑터 접근 방식 구현입니다.

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

두 어댑터 구현은 거의 동일하며 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) (리더 반환)
  • java.io.OutputStreamWriter(OutputStream) (Writer 반환)

이것이 자바의 어댑터 디자인 패턴에 대한 전부입니다.