- 한 클래스의 인터페이스를 클라이언트에서 사용하고자하는 다른 인터페이스로 변환한다.
- 어탭터를 이용하면 인터페이스 호환성 문제 때문에 같이 쓸 수 없는 클래스들을 연결해서 쓸 수 있다.
public interface Duck {
public void quack();
public void fly();
}
public class MallardDuck implements Duck {
@Override
public void quack() {
System.out.println("Quack");
}
@Override
public void fly() {
System.out.println("I'm flying");
}
}
public interface Turkey {
public void gobble();
public void fly();
}
public class WildTurkey implements Turkey {
@Override
public void gobble() {
System.out.println("Gobble gobble");
}
@Override
public void fly() {
System.out.println("I'm flying a short distance");
}
}
Duck 객체가 모자라서 Turkey 객체를 대신 사용해야하는 상황일때, 인터페이스가 다르기 때문에 Turkey 객체를 바로 사용할 수 없다. 사용하기 위해 아래에 어탭터를 만들어본다.
public class TurkeyAdapter implements Duck {
Turkey turkey;
public TurkeyAdapter(Turkey turkey) {
this.turkey = turkey;
}
@Override
public void quack(){
turkey.gobble();
}
@Override
public void fly() {
turkey.fly();
}
}
public class DuckTestDrive {
public static void main(String[] args) {
MallardDuck duck = new MallardDuck();
WildTurkey turkey = new WildTurkey();
Duck turkeyAdapter = new TurkeyAdapter(turkey);
System.out.println("The turkey says...");
turkey.gobble();
turkey.fly();
/*
The turkey says...
Gobble gobble
I'm flying a short distance
*/
System.out.println("The Duck says...");
testDuck(duck);
/*
The Duck says...
Quack
I'm flying
*/
System.out.println("The TurkeyAdapter says...");
testDuck(turkeyAdapter);
/*
The TurkeyAdapter says...
Gobble gobble
I'm flying a short distance
*/
}
public static void testDuck(Duck duck){
duck.quack();
duck.fly();
}
}
Duck 타입 TurkeyAdapter Class와 Turkey 타입 wildTurkey Class의 결과값이 같은 것을 확인 할 수 있다.
-
오브젝트 어댑터
-
- Adapter는 Target 인터페이스의 request() 메소드를 구현 하기 위해 Adaptee 클래스의 method1() 메소드를 사용
- Client는 Adapter 클래스를 통해 Adaptee를 Target 인터페이스의 구상 클래스처럼 사용할 수 있다.
-
클래스 어댑터
-
- Class Adapter는 다중 상속을 사용한다.
- Adapter가 Target클래스와 Adaptee클래스를 둘 다 상속하여 Target클래스가 필요한 곳, Adaptee클래스가 필요한 곳 모두 사용 될 수 있다.
Client : 써드파티 라이브러리나 외부시스템을 사용하려는 쪽
Adaptee : Client가 사용하려는 써드파티 라이브러리나 외부시스템(위 예제에서는 Turkey)
Adapter : Client와 Adaptee 중간에서 호환성이 없는 둘을 연결시켜주는 역할을 담당한다. Target Interface를 구현하며, Client는 Target Interface를 통해 Adapter에게 요청을 보낸다. Adapter는 Client의 요청을 Adaptee가 이해할 수 있는 방법으로 전달하고 Adaptee에서 처리가 이루어진다.
Target Interface : Adapte가 구현(implements)하는 인터페이스이다. 클라이언트는 Target Interface를 통해 Adaptee인 써드파티 라이브러리를 사용하게 된다. (위 예제에서는 Duck)
-
관계가 없는 인터페이스 간 같이 사용가능
-
프로그램 검사가 용이하다.
-
클래스 재활용성이 증가한다.
-
상속이 아닌 구성(Composition)을 이용하기 때문에 Adaptee의 모든 서브클래스에서 어댑터를 사용가능
-
Object Adapter Class Adapter 장점 상속이 아닌 구성을 사용하기 때문에 더 유연하다. Adapter가 Adaptee의 서브 클래스이기 때문에 Adaptee의 행동을 오버라이드 할 수 있다.
Adaptee 객체를 만들지 않아도 된다.단점 Adaptee 객체를 만들어야 사용가능하다. 상속을 이용하기 때문에 한 Adapter 클래스가 특정 Adaptee클래스에만 적용가능하다.
다중상속이 지원되는 언어에서만 사용가능하다.
- https://niceman.tistory.com/141
- https://gdtbgl93.tistory.com/141
- https://jusungpark.tistory.com/22
- https://yaboong.github.io/design-pattern/2018/10/15/adapter-pattern
- https://invincibletyphoon.tistory.com/20
어댑터 패턴은 호환성이 맞지 않는 클래스를 연관된 관계로 연결하여 사용할 수 있게끔 만들 수 있는 패턴