특정 클래스나 인터페이스를 클라이언트에서 요구하는 다른 인터페이스로 변환하여
기존에는 호환되지 않아서 같이 사용할 수 없던 클래스를 사용할 수 있게 해주는 디자인 패턴
어뎁터 패턴은
A(기존의 클래스나 인터페이스)를
B(상속,구현하지 않은 다른 객체)가
A(해당 클래스나 인터페이스에) 적용되기 위해서
A(해당 클래스나 인터페이스)를 구현 상속한
C(어뎁터클래스)의 멤버필드로 들어가는 것이다.
데코레이터 패턴은
기존 클래스나 인터페이스에다가 새로운 기능을 추가, 확장하기 위해서
해당 클래스타입의 객체를 멤버로 갖고 새로운 기능을 추가하는
래퍼클래스(Wrapper)를 만드는 것이다.
public interface PowerPlug110 {
public void charge();
public void plugWith110();
}
public interface PowerPlug220 {
public void charge();
public void plugWith220();
}
여기, 110V 혹은 220V로 충전하는 플러그 인터페이스 2가지가 있다.
public class Charger110 implements PowerPlug110 {
@Override
public void charge() {
System.out.println("110V 전용 충전기로 충전 중입니다");
}
@Override
public void plugWith110() {
System.out.println("110V 플러그에 꽂았습니다");
}
}
public class Charger220 implements PowerPlug220 {
@Override
public void charge() {
System.out.println("220V 전용 충전기로 충전 중입니다");
}
@Override
public void plugWith220() {
System.out.println("220V 플러그에 꽂았습니다");
}
}
해당 플러그 인터페이스들을 각각 구현한 110V짜리 충전기와 220V짜리 충전기가 있다.
하지만, 클라이언트가 만약에 220V충전기로 110V 플러그에 꽂아 110V로 충전을 하고싶다면 어떻게 해야할까?
이때 사용하는 패턴이 바로 어뎁터 패턴인 것이다
public class AdapterFrom110To220 implements PowerPlug110 {
Charger220 charger;
// 220V 충전기를 꽂을 수 있는 어뎁터
public AdapterFrom110To220(Charger220 charger) {
this.charger = charger;
}
@Override
public void charge() {
charger.charge();
}
@Override
public void plugWith110() {
System.out.println("110V 플러그에 꽂았습니다");
}
}
public static void main(String[] args) {
Charger220 charger = new Charger220();
AdapterFrom110To220 adapter = new AdapterFrom110To220(charger);
adapter.charge(); // 220V 전용 충전기로 충전 중입니다.
adapter.plugWith110(); // 110V 플러그에 꽂았습니다.
}
위와 같이 220V 충전기를 어뎁터를 이용해서 110V플러그에 연결하여 사용하듯이
어뎁터패턴도 어뎁터클래스를 이용해서 같이쓸수 없는 클래스와 연결해서 사용이 가능하다.
어뎁터 패턴에는 객체 어뎁터와 클래스 어뎁터가 있다.
객체 어뎁터는 Target(PowerPlug110) 인터페이스를 구현하고
Adaptee(Charger220) 클래스 객체를 멤버로 가져 해당 객체의 메소드를 위임받는다.
이와는 다르게 클래스 어뎁터는 말그대로 두 클래스 모두를 상속받는 서브클래스를 만들어서 사용한다.
자바는 다중 상속을 지원하지 않기 때문에 클래스 어뎁트를 사용하지 않고 객체 어뎁터를 사용한다.