본문 바로가기
Study/디자인 패턴

[C#/Unity][디자인패턴] 어댑터 패턴(Adapter Pattern)

by 스테디코디스트 2023. 11. 23.
반응형

1. 어댑터 패턴이란?

- 클래스의 인터페이스를 사용자가 기대하는 다른 인터페이스로 변환하는 패턴.

- 두 객체 사이의 래퍼 역할을 함.

- 호환되지 않는 객체들이 협업할 수 있게 함.

- 기존 코드를 클라이언트가 사용하는 인터페이스의 구현체로 바꿔주는 패턴.

- 하나의 객체에 대한 호출을 캐치하고 두 번째 객체가 인식할 수 있는 형식과 인터페이스로 변환시켜줌.

 

2. 어댑터 패턴을 사용하는 경우

- 버그가 없이 이미 존재하는 클래스를 재사용하는 경우

- 이미 만들어진 클래스를 새로운 인터페이스에 맞게 개조시키는 경우

- 오픈소스를 사용하거나 프로젝트 중간에 합류해서 작업해야 하는 경

 

3. 어댑터 패턴의 장점

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

2) 보존성 : 기존의 두 소스는 수정할 필요가 없고, 어댑터 클래스만 추가되어 둘 사이를 연결해준다.

3) 확장성 : 기존의 클래스에 새로운 기능을 추가해서 신규 클래스 같은 기능을 하게 할 수 있음.

4) 캡슐화 : 상세한 내부 코드의 흐름을 몰라도 되고, 버그를 찾기 쉬움

 

4. 어댑터 패턴의 단점

1) 복잡성 증가 : 소스코드가 늘어나 코드의 복잡성을 증가시켜 유지보수가 어려워질 수 있음.

2) 처리시간 증가 : 어댑터가 중간에서 데이터를 변환하는 과정이 추가적인 처리 시간과 오버 헤드를 발생시킬 수 있음.

 

5. 코드 구현

1) 위임을 이용

- 두 개의 클래스 중 한 쪽 클래스의 함수를 다른 쪽 클래스에서 사용하고 싶을 때 사용한다.

- 아래 예시는 카드결제만 가능한 상황에서 카드가 없을 때 어댑터 패턴을 이용해 현금으로 계산하는 방법이다.

1. 카드 인터페이스를 상속받은 어댑터 클래스에서 현금 인터페이스 객체를 만들어준다.

2. 생성자를 이용해 어댑터 객체 생성시 현금 객체를 연결해준다.

3. 카드 인터페이스의 구현 함수를 오버라이드할 때 현금 객체의 결제 함수를 콜해준다.

using System;

namespace StudyCSharp
{
    // 현금
    public interface Cash 
    {
        void Charge(); // 결제
    }

    // 카드
    public interface Card
    {
        void Pay(); // 결제
    }

    // 지폐
    public class Bill : Cash
    {
        int _money; // 보유한 현금의 양

        public Bill(int money)
        {            
            _money = money;
        }

        public void Charge()
        {
            Console.WriteLine("현금 {0}원 결제", _money);
        }
    }

    // 체크카드
    public class CheckCard : Card
    {
        int _money; // 카드 잔액

        public CheckCard(int money)
        {
            _money = money;
        }

        public void Pay()
        {
            Console.WriteLine("카드 {0}원 결제", _money);
        }

        public void Lost()
        {
            Console.WriteLine("카드 분실");
        }
    }

    // 어댑터 패턴
    // 카드지만 현금을 이용할 수 있음
    public class MoneyAdapter : Card
    {
        Cash cash;

        public MoneyAdapter(Cash cash)
        {
            Console.WriteLine("어댑터 카드 생성");
            this.cash = cash;
        }

        public void Pay()
        {
            Console.WriteLine("사용 가능한 카드가 없어 어댑터 카드로 대신 결재합니다.");
            cash.Charge();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Bill myBill = new Bill(10000); // 보유현금 
            CheckCard myCard = new CheckCard(5000); // 보유카드 

            // <상황>
            // 카드결제만 가능한 상황, 처음에는 카드로 잘 결제를 했지만,
            // 카드를 분실하여 두번째 결제시에는 현금으로 대신 결제

            // 첫번째 결제 -> 카드가 있으므로 카드로 계산
            myCard.Pay();

            // 카드 분실
            myCard.Lost();

            // 카드로만 결제가 가능하기 때문에, 현재 보유한 현금으로 만들 수 있는 어댑터카드 생성
            Card adapterCard = new MoneyAdapter(myBill);

            // 두번째 결제 -> 어댑터 카드로 결제
            adapterCard.Pay();
        }
    }        
}

 

2) 상속을 이용

- 다중상속을 이용하도록 기존 클래스를 변경하여 실행코드는 동일하게 유지한채 출력을 바꾸고 싶을 때 사용할 수 있다.

- 새로운 인터페이스를 만들고, 기존 인터페이스만 상속되있던 것에 추가로 상속시켜주고, 새로운 인터페이스의 구현 함수를 오버라이드하여 정의해준뒤, 기존 인터페이스 오버라이드 함수에서 콜 해준다.

using System;

namespace StudyCSharp
{
    // 현금
    public interface Cash 
    {
        void Charge(); // 결제
    }

    // 카드
    public interface Card
    {
        void Pay(); // 결제
    }

    // 기존 클래스
    //public class Adapter : Cash
    //{
    //    public void Charge()
    //    {
    //        Console.WriteLine("현금 결제");
    //    }
    //}
   
    // 어댑터 클래스 - 다중상속 이용
    public class Adapter : Cash, Card
    {
        public void Charge()
        {
            Pay();
        }

        //////////////////////////////////////////////////////////////

        public void Pay()
        {
            Console.WriteLine("어댑터 카드 결제");
        }
    }
                
    class Program
    {
        static void Main(string[] args)
        {
            // 어댑터 패턴 사용 전 코드와 동일
            // 기존 클래스를 어댑터 클래스로 변경하여 출력을 변화시킬 수 있음.
            Adapter card = new Adapter();
            card.Charge();
        }
    }        
}


<참고 사이트>

 

C#으로 작성된 어댑터 / 디자인 패턴들

 

refactoring.guru

 

 

어댑터 패턴 [Adapter Pattern] : 바꿔서 다시 이용하기

어댑터는 우리가 일상생활 속에서 잘 사용하고 있는 물건중 하나이다. 예를 들어 HDMI 케이블에 MiniHDMI 어댑터를 사용하여 HDMI to MiniHDMI 처럼 사용한다든지, 110V짜리 플러그를 어댑터를 사용하여 2

orcacode.tistory.com

 

 

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

[읽기전에] UML 다이어그램 : UML클래스 다이어그램 기본상식 http://hongjinhyeon.tistory.com/25 포스팅되는 디자인 패턴의 예는 스타크래프트를 기본으로 하였습니다 : 디자인 패턴을 시작하며 http://hongji

hongjinhyeon.tistory.com

 

 

[디자인패턴] 9. 유니티에서의 어댑터 패턴 퍼사드 패턴

이번 챕터에서는 두개의 패턴이 함께 있어서 같이 작성했습니다. 첫번째로 어댑터 패턴입니다. 어댑터 패턴 정의 한 클래스의 인터페이스를 클라이언트에서 사용하고자 하는 다른 인터페이스

welcomeheesuk.tistory.com

 

[구조 패턴] Chapter 6-1. Adapter Pattern : 패턴 소개

✍️ 어댑터 패턴, 패턴 소개 어댑터 패턴은 일상생활에서도 흔히 찾아볼 수 있는데, 220V 코드를 110V 콘센트에 꽂을 때 흔히 돼지코라고 불리는 어댑터를 사용해 본 경험이 있을 것이다. 바로 이

kangworld.tistory.com

 

 

Chapter 13. 어댑터 패턴(Adapter Pattern)

인프런에 있는 이재환님의 강의 게임 디자인 패턴 with Unity 를 듣고 정리한 필기입니다. 😀

ansohxxn.github.io

 

 

어댑터 패턴 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전.

ko.wikipedia.org