본문 바로가기

설계

[파이썬] 포트와 어댑터 패턴

포트와 어댑터 패턴은 소프트웨어 디자인 패턴 중에서, 소프트웨어 컴포넌트간의 연결을 관리하고, 서로 다른 인터페이스를 갖는 객체들간의 상호작용을 가능하게 해주는 패턴입니다.

포트(Port)는 인터페이스를 나타내며, 송수신 가능한 통신 채널을 제공합니다.
어댑터(Adapter)는 서로 다른 인터페이스를 가진 객체들 간의 상호작용을 가능하게 해주는 중간 역할을 수행합니다. 어댑터는 포트를 통해 객체들 간의 상호작용을 담당합니다.

 

1. 예제 코드

 

다음은 파이썬 예제 코드로 포트와 어댑터 패턴을 설명하겠습니다.

 

# 포트 인터페이스 정의
class PaymentPort:
    def process_payment(self, amount):
        pass

# 포트 구현체1: 신용카드 결제
class CreditCardPayment(PaymentPort):
    def process_payment(self, amount):
        # 신용카드 결제 처리 로직
        print(f"Credit card payment of ${amount} processed successfully.")

# 포트 구현체2: 페이팔 결제
class PayPalPayment(PaymentPort):
    def process_payment(self, amount):
        # 페이팔 결제 처리 로직
        print(f"PayPal payment of ${amount} processed successfully.")

# 어댑터 클래스 정의
class PaymentAdapter:
    def __init__(self, payment_system):
        self.payment_system = payment_system

    def process_payment(self, amount):
        # 어댑터를 통해 호출된 메서드를 내부 포트를 이용해 연결된 객체의 메서드로 전달
        self.payment_system.process_payment(amount)

# 클라이언트 코드
if __name__ == '__main__':
    # 페이팔 결제
    paypal_payment = PaymentAdapter(PayPalPayment())
    paypal_payment.process_payment(100)

    # 신용카드 결제
    credit_card_payment = PaymentAdapter(CreditCardPayment())
    credit_card_payment.process_payment(200)


위 코드에서는 먼저 PaymentPort 인터페이스를 정의하고, 이를 구현한 CreditCardPayment과 PayPalPayment 클래스를 만듭니다. 그리고 PaymentAdapter 클래스를 만들어 이 클래스를 통해 PaymentPort를 구현한 객체를 연결합니다.

클라이언트 코드에서는 PaymentAdapter를 사용하여 PayPalPayment와 CreditCardPayment 객체를 생성하고, 이를 통해 process_payment() 메서드를 호출합니다. 이때 PaymentAdapter 내부에서는 어댑터를 통해 포트를 이용해 객체의 메서드를 호출합니다.

이렇게 포트와 어댑터 패턴을 사용하면, 서로 다른 인터페이스를 갖는 객체들 간의 상호작용을 가능하게 해줍니다. 또한, 객체간의 결합도를 낮춰줌으로써 유지보수성과 재사용성을 높일 수 있습니다. 예를 들어, 새로운 결제 시스템을 추가할 경우, PaymentPort 인터페이스를 구현하고 PaymentAdapter를 만들어서 클라이언트 코드를 수정하지 않고 새로운 결제 시스템을 추가할 수 있습니다.

 

2. 장점

  • 서로 다른 인터페이스를 갖는 객체들 간의 상호작용을 가능하게 해줍니다.
  • 결합도를 낮춰 유지보수성과 재사용성을 높일 수 있습니다.
  • 새로운 객체를 추가할 때, 기존 코드를 수정하지 않고 쉽게 추가할 수 있습니다.

 

3. 단점

  • 구현이 복잡할 수 있습니다.
  • 런타임 오버헤드가 존재할 수 있습니다.
  • 너무 많은 어댑터가 생성될 경우, 코드가 복잡해질 수 있습니다.