전체 페이지뷰

2017년 3월 3일 금요일

Adaptor Pattern

어댑터 패턴은 말 그대로 호환성이 없는 것들을 연결해주어 동작할 수 있게 해주는 패턴을 말합니다. 구멍 모양이나 크기가 맞지 않는 전원 플러그 앞에 끼워 사용할 수 있게 해주는 그런 어댑터를 연상하면 되겠습니다.
객체 지향 프로그래밍 영역에서는 새로 추가한 클래스 라이브러리가 기존에 사용하던 인터페이스와 달라 사용이 어려울 때, 둘 사이를 연결해주는 가교 역할을 합니다.

이제 이해를 돕기 위해 1장에서 친숙해진 오리의 예를 들어봅니다. Duck 인터페이스를 단순화 시켜서 사용하겠습니다.
public interface Duck
{
    void Quack();
    void Fly();
}
cs

Duck을 구현하는 MallardDuck 클래스는 다음과 같습니다.
public class MallardDuck : Duck
{
    public void Quack()
    {
        Console.WriteLine("Quack");
    }
    public void Fly()
    {
        Console.WriteLine("I'm flying!");
    }
}
cs

여기 새로운 조류의 인터페이스가 등장합니다. 바로 칠면조입니다.
public interface Turkey
{
    void Gobble();
    void Fly();
}
cs
인터페이스가 비슷합니다만 다릅니다. 이 칠면조를 구현한 WildTurkey 클래스를 작성합니다.
public class WildTurkey : Turkey
{
    public void Gobble()
    {
        Console.WriteLine("Gobble gobble");
    }
    public void Fly()
    {
        Console.WriteLine("I'm flying a short distance");
    }
}
cs


이제 Duck 객체가 모자라서(?) Turkey 객체를 대신 써야하는 상황이라고 가정하고, Turkey 객체를 이용할 수 있는 어댑터를 만들어 보겠습니다.
public class TurkeyAdapter : Duck
{
    Turkey turkey;
    public TurkeyAdapter(Turkey turkey)
    {
        this.turkey = turkey;
    }
    public void Quack()
    {
        turkey.Gobble();
    }
    public void Fly()
    {
        for (int i = 0; i < 5; i++)
        {
            turkey.Fly();
        }         
    }
}
cs

내부에 Turkey의 레퍼런스가 존재합니다. 그리고, Quack()은 해당 자리에 그냥 Gobble()메소드를 호출했고, 칠면조는 나는 거리가 짧아 5회 날기를 반복시켰습니다.

이제 테스트를 작성합니다.
static void TestDuck(Duck duck)
{
    duck.Quack();
    duck.Fly();
}
        
static void Main(string[] args)
{
    MallardDuck duck = new MallardDuck();
    WildTurkey turkey = new WildTurkey();
    Duck turkeyAdapter = new TurkeyAdapter(turkey);
    Console.WriteLine("The Turkey says...");
    turkey.Gobble();
    turkey.Fly();
    Console.WriteLine("\nThe Duck says...");
    TestDuck(duck);
    Console.WriteLine("\nThe Turkey says...");
    TestDuck(turkeyAdapter);
}
cs

Duck과 Turkey 객체를 생성하고 Turkey는 TurkeyAdapter로 감싸서 Duck처럼 보이게 만듭니다. 정적 메소드인 TestDuck()을 사용해서 오리 대신 칠면조를 넣어봤습니다.

결과)
The Turkey says...
Gobble gobble
I'm flying a short distance

The Duck says...
Quack
I'm flying!

The Turkey says...
Gobble gobble
I'm flying a short distance
I'm flying a short distance
I'm flying a short distance
I'm flying a short distance
I'm flying a short distance
계속하려면 아무 키나 누르십시오 . . .



어댑터 패턴의 정의


어댑터 패턴: 한 클래스의 인터페이스를 클라이언트에서 사용하고자 하는 다른 인터페이스로 변환합니다. 어댑터를 이용하면 호환성 문제 때문에 같이 쓸 수 없는 클래스들을 연결해서 사용 가능합니다.


여기서  Target은 Duck 클래스입니다. Adaptee는 Turkey클래스 이지요. 중간 TurkeyAdaptor로 타겟인 Duck을 구현한 것입니다.

이 어댑터 패턴이 하는 일과 비슷한 일들을 하는 패턴이 있습니다.
하나는 전에 살펴본 데코레이터 패턴이고, 다른 하나는 다음에 보게될 퍼사드(Facade) 패턴입니다.

그 용도를 간략하게 짚어보고 퍼싸드 패턴으로 이어가겠습니다.


  • 데코레이터 - 인터페이스는 바꾸지 않고 기능만 추가
  • 어댑터 - 한 인터페이스를 다른 인터페이스로 전환
  • 퍼사드 - 하나 이상의 복잡한 인터페이스를 간단하게 바꿈



댓글 없음:

댓글 쓰기