어댑터 패턴

정선호·2023년 5월 18일
0

Design Patterns

목록 보기
12/24

관련 문서

어댑터 패턴

위키피디아 - 어댑터 패턴
설명 및 스도코드

  • 클래스의 인터페이스를 사용자가 기대하는 다른 인터페이스로 변환하는 패턴으로, 호환성이 없는 인터페이스 때문에 함께 동작할 수 없는 클래스들이 함께 작동하도록 해준다.

어댑터 패턴의 구조

  • 클라이언트(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();
    }
}
profile
학습한 내용을 빠르게 다시 찾기 위한 저장소

0개의 댓글