Adapter 패턴
한 클래스의 인터페이스를 클라이언트에서 사용하고자하는 다른 인터페이스로 변환한다.
어댑터를 이용하면 인터페이스 호환성 문제 때문에 같이 쓸 수 없는 클래스들을 연결해서 쓸 수 있다.
예제
1 | public class IteratorToEnumeration implements Enumeration<String>{ |
최종족으로 사용하고자 하는 메서드는 goodMethod()이다.
하지만 iterator을 가지고 있는 List는 Enumeration 인자가 없기 때문에 사용하지 못한다.
이때 IteratorToEnumeration 클래스가 iterator를 받아서 Enumeration 클래스를 사용 할 수 있도록 Enumeration 인터페이스의 메서드를 구현 한다.
AtoB의 형태를 가지는 Adapter는 A를 멤버변수로 가지고 B를 구현한다.
Adapter를 구현하는 방법
위에서 소개된 방법은 “구성을 통한 방법” 또는 “위임을 통한 방법” 이다. Adapter 자체는 하는 일이 별로 없다. 내부적으로 멤버한테다가 일을 다 떠넘긴다. 외관상 다른 형태로 변환가능하기 위한 것이지 어떤 일을 직접할려는 것은 아니다.
두번째 방법은 상속을 이용하는 방법이다. A to B로 할 경우 A와 B를 둘다 구현하는 방법이다. A와 B가 둘 다 인터페이스거나, 하나만 인터페이스일 때는 가능하지만, 둘 다 클래스일 경우에는 불가능하다.
세번째 방법은 Adapter 클래스를 만들지 않고 method로 만드는 방법이다.1
2
3
4
5
6
7
8
9
10
11public static Enumeration<String> iteratorToEnumeration(final Iterator<String> iter) {
return new Enumeration<String>() {
public boolean hasMoreElements() {
return iter.hasNext();
}
public String nextElement() {
return iter.next();
}
};
}
눈치 빠른 사람들은 인자가 final이란 것을 봤을 것이다. final로 말뚝 박는 건 “변경 절대 불가!” 를 보장하는 것이다. 메서드 안에서 Enumeration의 구현체가 인자로 받은 것을 사용하는데, 이런 경우에는 인자가 final 로 정의되어야 하며, 그렇지 않을 경우 컴파일시에 문제가 된다.
final로 정의한다는 것은 read-only라는 뜻이다. 주의할 것은 read-only라는 게 다른 변수로 할당을 못한다는 것 뿐 내부의 메서드를 호출하지 못한다는 것은 아니다. (메서드 내부에서 iter = 다른것; 이런식으로 사용하지 못한다는 이야기다.)
세번째 방법은 Adapter 패턴이라고 불리지는 않는다. 그러나 하는 일이 비슷하다.