본문 바로가기
OOP/<헤드 퍼스트 디자인 패턴>, 에릭 프리먼 외

Adapter

by 민휘 2023. 2. 24.

핵심 의도

특정 클래스 인터페이스를 클라이언트에서 요구하는 다른 인스턴스로 변환한다. 인터페이스가 호환되지 않아 같이 쓸 수 없었던 클래스를 사용할 수 있게 도와준다.

 

적용 상황

클라이언트가 기존에 사용하고 있는 인터페이스가 있는데, 호환되지 않는 새로운 인터페이스를 기존 인터페이스(타깃)으로 사용하고 싶을 때 어댑터 패턴을 사용한다.

 

솔루션의 구조와 각 요소의 역할

위의 그림은 객체 어댑터의 구조. 다중 상속이 가능한 언어로 클래스 어댑터도 만들 수 있다. 타깃과 어댑티를 상속하여 어댑터를 만든다.

 

객체에게 책임을 분할하기

우선 클라이언트가 기존에 사용하고 있는 인터페이스가 Target이다. 그리고 새롭게 사용하려고 하는 인터페이스가 Adaptee이다. 클라이언트가 Adaptee를 Target 타입으로 사용하려면 이 둘 사이에 요청을 통과시켜줄 수 있는 책임이 필요한데, 이를 Adapter가 수행한다.

 

구현 포인트

어댑터 클래스는 타깃 인터페이스를 구현하고, 어댑티 클래스를 구성으로 가진다. 그래서 타깃 인터페이스로 메시지가 요청이 오면 어댑티의 메시지를 호출하여 메시지를 통과시킨다.

 

적용 예시

 

요구사항

기존에 사용하던 Iterator 인터페이스에 Enumeration 인터페이스를 추가로 사용하려고 한다. 클라이언트는 Iterator 타입으로 Enumeration을 사용한다.

 

설계

어댑터인 EnumerationIterator는 타깃인 Iterator을 구현하고 어댑티인 Enumeration을 구성으로 가진다. Iterator의 추상 메소드를 구현할 때 Enumeration의 메소드를 호출하면 되는데, remove()는 대응하는 메소드가 없으므로 예외를 던진다. 클라이언트는 어댑터를 통해 Iterator로 Enumeration을 사용할 수 있다.

 

코드

EnumerationIterator

public class EnumerationIterator implements Iterator<Object> {
	Enumeration<?> enumeration;
 
	public EnumerationIterator(Enumeration<?> enumeration) {
		this.enumeration = enumeration;
	}
 
	public boolean hasNext() {
		return enumeration.hasMoreElements();
	}
 
	public Object next() {
		return enumeration.nextElement();
	}
 
	public void remove() {
		throw new UnsupportedOperationException();
	}
}

EnumerationIteratorTest

public class EnumerationIteratorTestDrive {
	public static void main (String args[]) {
		Vector<String> v = new Vector<String>(Arrays.asList(args));
		// Iterator 타입으로 Enumeration 사용 중
		Iterator<?> iterator = new EnumerationIterator(v.elements());
		while (iterator.hasNext()) {
			System.out.println(iterator.next());
		}
	}
}

'OOP > <헤드 퍼스트 디자인 패턴>, 에릭 프리먼 외' 카테고리의 다른 글

Template Method  (0) 2023.02.24
Facade  (0) 2023.02.24
Command  (0) 2023.02.24
Singleton  (0) 2023.02.24
Simple Factory, Factory Method, Abstract Factory  (0) 2023.02.24