관련 문서
어댑터 패턴
위키피디아 - 어댑터 패턴
설명 및 스도코드
- 클래스의 인터페이스를 사용자가 기대하는 다른 인터페이스로 변환하는 패턴으로, 호환성이 없는 인터페이스 때문에 함께 동작할 수 없는 클래스들이 함께 작동하도록 해준다.
어댑터 패턴의 구조
- 클라이언트(Client)
- 프로그램의 기존 비즈니스 로직을 포함하는 클래스
- 클라이언트 인터페이스(Client Interface)
- 다른 클래스들이 클라이언트 코드와 공동 작업할 수 있도록 따라야 하는 프로토콜
- 서비스(Sevice)
- 일반적으로 타사 또는 레거시의 유용한 클래스
- 서비스 클래스는 호환되지 않는 인터페이스를 갖고있기 때문에 클라이언트는 서비스 클래스를 직접 사용할 수 없다.
- 어댑터(Adapter)
- 클라이언트와 서비스 양쪽에서 작동할 수 있는 클래스
- 서비스 객체를 래핑하는 동안 클라이언트 인터페이스 구현
- 어댑터 인터페이스를 통해 클라이언트로부터 호출들을 수신한 후 이 호출을 래핑된 서비스 객체가 이해할 수 있는 형식의 호출로 변환
어댑터 패턴의 적용
- 기존 클래스를 사용하고 싶지만 그 인터페이스가 나머지 코드와 호환되지 않을 때
- 부모 클래스에 추가할 수 없는 어떤 공통 기능들이 없는 여러 기존 자식 클래스들을 재사용하려는 경우
다른 패턴과의 관계
- 브리지는 일반적으로 사전에 설계되며, 앱의 다양한 부분을 독립적으로 개발할 수 있도록 한다. 반면에 어댑터는 일반적으로 기존 앱과 사용되어 원래 호환되지 않던 일부 클래스들이 서로 잘 작동하도록 한다.
- 어댑터는 기존 객체의 인터페이스를 변경하는 반면 데코레이터는 객체를 해당 객체의 인터페이스를 변경하지 않고 향상한다. 또한 데코레이터는 어댑터를 사용할 때는 불가능한 재귀적 합성을 지원한다.
- 어댑터는 다른 인터페이스를, 프록시는 같은 인터페이스를, 데코레이터는 향상된 인터페이스를 래핑된 객체에 제공한다.
- 퍼사드는 기존 객체들을 위한 새 인터페이스를 정의하는 반면 어댑터는 기존의 인터페이스를 사용할 수 있게 만들려고 노력한다. 또 어댑터는 일반적으로 하나의 객체만 래핑하는 반면 퍼사드는 많은 객체의 하위시스템과 함께 작동한다.
- 브리지, 상태, 전략 패턴은 매우 유사한 구조로 되어 있으며, 어댑터 패턴도 이들과 어느 정도 유사한 구조로 되어 있다. 위 모든 패턴은 다른 객체에 작업을 위임하는 합성을 기반으로 한다. 하지만 이 패턴들은 모두 다른 문제들을 해결한다. 패턴은 특정 방식으로 코드의 구조를 짜는 레시피에 불과하지 않는다. 왜냐하면 패턴은 해결하는 문제를 다른 개발자들에게 전달할 수도 있기 때문이다.
어댑터 패턴을 이용 칠면조를 오리로 바꾸기
public interface Duck
{
void quack(); // 꽥 울기
void fly(); // 날기
}
public class MallardDuck : Duck
{
public void quack()
{
Debug.Log("오리 : 울기(꽥꽥)");
}
public void fly()
{
Debug.Log("오리 : 날기");
}
}
public interface Turkey
{
void gobble(); // 울기
void fly(); // 날기
}
public class WildTurkey : Turkey
{
public void gobble()
{
Debug.Log("칠면조 : 울기(고르륵고르륵)");
}
public void fly()
{
Debug.Log("칠면조 : 날기");
}
}
- 칠면조를 오리로 바꿔주는 어댑터
- 오리 인터페이스를 상속해 각각 함수들 안에서 이에 대응하는 칠면조의 함수 호출
public class TurkeyAdapter : Duck
{
Turkey turkey;
public TurkeyAdapter(Turkey turkey)
{
this.turkey = turkey;
}
public void quack()
{
turkey.gobble();
}
public void fly()
{
turkey.fly();
}
}
public class Client : MonoBehaviour {
void Start () {
MallardDuck duck = new MallardDuck();
WildTurkey turkey = new WildTurkey();
Duck turkeyAdapter = new TurkeyAdapter(turkey);
Debug.Log("오리 사용...");
testDuck(duck);
Debug.Log("오리 부족. 칠면조로 대체...");
testDuck(turkeyAdapter);
}
void testDuck(Duck duck)
{
// 동일한 방법으로 사용
duck.quack();
duck.fly();
}
}