4. Adapter Pattern ( 어댑터 / 적응자 패턴 C# )

|

[읽기전에]

  UML 다이어그램 : UML클래스 다이어그램 기본상식 http://hongjinhyeon.tistory.com/25 

  포스팅되는 디자인 패턴의 예는 스타크래프트를 기본으로 하였습니다 : 디자인 패턴을 시작하며 http://hongjinhyeon.tistory.com/24



<기본 정의 >


1. Adapter Pattern 정의


  -한 클래스의 인터페이스를 클라이언트에서 사용하고자 하는 다른 인터페이스로 변환한다.

   인터페이스 호환성 문제 때문에 같이 쓸 수 없는 클래스들을 연결해서 쓸 수가 있다.


   (Convert the interface of a class into another interface clients expect. 

    Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.)


 -신식의 클래스에 구식의 클래스를 연동해서 사용이 가능하게 할 수가있다.


 -실생활을 예를 들면, 기존에 110V의 전자제품을 220V로 변환해주는 어댑터가 이 패턴이랑 유사하다.

 



2. UML Diagram





3. 사용용도 및 장점


 -서로 달라서 같이 쓰지 못하는 클래스들을 연결해서 하나의 인터페이스로 사용이 가능하다.


 -두개의 소스는 전혀 수정이 되지 않고 어댑터 클래스가 추가되어 두개의 사이를 연결해준다.


 -기존의 클래스에 새로운 기능을 추가해서 신규 클래스 같은 기능을 하게 할 수 있다.

 



4. 소스

using System;
 
namespace DoFactory.GangOfFour.Adapter.Structural
{
  /// <summary>
  /// MainApp startup class for Structural
  /// Adapter Design Pattern.
  /// </summary>
  class MainApp
  {
    /// <summary>
    /// Entry point into console application.
    /// </summary>
    static void Main()
    {
      // Create adapter and place a request
      Target target = new Adapter();
      target.Request();
 
      // Wait for user
      Console.ReadKey();
    }
  }
 
  /// <summary>
  /// The 'Target' class
  /// </summary>
  class Target
  {
    public virtual void Request()
    {
      Console.WriteLine("Called Target Request()");
    }
  }
 
  /// <summary>
  /// The 'Adapter' class
  /// </summary>
  class Adapter : Target
  {
    private Adaptee _adaptee = new Adaptee();
 
    public override void Request()
    {
      // Possibly do some other work
      //  and then call SpecificRequest
      _adaptee.SpecificRequest();
    }
  }
 
  /// <summary>
  /// The 'Adaptee' class
  /// </summary>
  class Adaptee
  {
    public void SpecificRequest()
    {
      Console.WriteLine("Called SpecificRequest()");
    }
  }
}



5. 실행결과


  Called SpecificRequest()




< 실제 적용 >



1. UML Diagram






2. 사용용도 및 장점

 

 -스타크래프트를 개발 후에 브루드워로 확장팩이 나오게 될때, 기존 유닛에 변경이 많이 되어서  새로운 형식의 유닛 클래스를 생성 한다고


   가정하자.  이 새로운 유닛은 인터페이스를 갖게 되는데 새로운 팀에서 개발이 되어서 이동 명령이 Move(), 정지 명령이 Stop() 이란 인터


   페이스를 생성을 했다. 그런데 기존의 팀에서 개발된 유닛 클래스는 이동 명령이 MoveToPoint(), 정지명령이 StopMove() 라고 했을때 


   이 둘을 하나의 인터페이스로 사용을 할 수가 없으니 어댑터를 이용해서 신규 개발된 클래스의 인터페이스로 기존 클래스의 함수를 사용하고


   신규 유닛 인터페이스에  맞도록 추가적인 기능을 넣어주면 된다.



 -기존 유닛들은 동일한 기능을 하며 새로운 기능을 추가 할 수도있으며 , 구식 유닛 클래스를 재사용을 할 수가 있게된다.

   



3. 소스

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Adapter
{
    class Program
    {
        static void Main(string[] args)
        {

            List<NewUnit> ltUnit = new List<NewUnit>();
            ltUnit.Add(new NewUnit()); //신규 유닛
            ltUnit.Add(new Unit()); //기존 유닛

            foreach (NewUnit newUnit in ltUnit)
            {
                //같은 소스로 제어가능
                newUnit.Move();
                newUnit.Stop();
            }

            Console.ReadKey();
        }

        /// <summary>
        /// 타겟 클래스
        /// </summary>
        class NewUnit
        {
            public virtual void Move()
            {
                Console.WriteLine("New Unit Moved !");
            }

            public virtual void Stop()
            {
                Console.WriteLine("New Unit Stopped !");
            }
        }

        /// <summary>
        /// 어뎁터클래스
        /// </summary>
        class Unit : NewUnit
        {
            private OldUnit _adaptee = new OldUnit();

            public override void Move()
            {
                _adaptee.MoveToPoint();
            }

            public override void Stop()
            {
                _adaptee.StopMove();
            }
           
        }

        /// <summary>
        /// 어뎁티 클래스
        /// </summary>
        class OldUnit
        {
            public void MoveToPoint()
            {
                Console.WriteLine("Old Unit Moved !");
            }

            public void StopMove()
            {
                Console.WriteLine("Old Unit Stopped !");
            }
        }

    }
}



4. 실행결과




-List<NewUnit> ltUnit = new List<NewUnit>(); 에서 리스트로 선언하고 아래에서 신규유닛과 기존 유닛을 생성 후에
  foreach로 신규/구 유닛 구별없이 동일한 소스로사용이 가능하다. 즉 구 유닛도 신규유닛과 같은 인터페이스로 제어가 가능하다.



5. 피드백


 - 이 패턴을 공부하면서 현업에서는 어떻게 사용이 될지를 생각해보았다. 보통 개발을 하다보면 여러회사의 콤포넌트를 연동을


   할 필요가 생기게 되는데 이럴때에 사용하면 좋겠다라는 생각이 들었다.



[참조]

 -http://www.dofactory.com


And