어댑터 패턴

호환성 높이기

Posted by Yan on January 25, 2024

adapter pattern

호환되지 않는 인터페이스를 가진 객체들이 협업할 수 있도록 하는 구조적 디자인 패턴

  • 어댑터는 한 객체의 인터페이스를 다른 객체가 이해할 수 있도록 변환하는 특별한 객체
  • 어댑터는 변환의 복잡성을 숨기기 위하여 객체 중 하나를 래핑(포장)다. 래핑된 객체는 어댑터를 인식하지도 못한다.

작동방식

  1. 어댑터는 기존에 있던 객체 중 하나와 호환되는 인터페이스를 받는다.
  2. 이 인터페이스를 사용하면 기존 객체는 어댑터의 메서드들을 안전하게 호출할 수 있다.
  3. 호출을 수신하면 어댑터는 이 요청을 두 번째 객체에 해당 객체가 예상하는 형식과 순서대로 전달한다.

구조 (객체어댑터)

  • 객체 합성 원칙 사용
  • 어댑터는 한 객체의 인터페이스를 구현하고, 다른 객체를 래핑함.

클라이언트

  • 프로그램의 기존 비즈니스로직을 포함하는 클래스

클라이언트 인터페이스

  • 다른 클래스들이 클라이언트 코드와 공동 작업할 수 있도록 따라야하는 프로토콜

서비스

  • 일반적으로 타사 또는 레거시의 유용한 클래스를 뜻함.
  • 클라이언트는 서비스 클래스를 직접 사용할 수 없다.
  • 왜냐하면 서비스 클래스는 호환되지 않는 인터페이스를 갖고 있기 때문

어댑터

  • 클라이언트와 서비스 양족에서 작동할 수 있는 클래스
  • 서비스 객체를 래핑하는 동안 클라이언트 인터페이스를 구현한다.
  • 어댑터 인터페이스를 통해 클라이언트로부터 호출들을 수신한 후 이 호출을 래핑된 서비스 객체가 이해할 수 있는 형식의 호출들로 변환한다.

구조 (클래스 어댑터)

  • 상속을 사용하며, 어댑터는 동시에 두 객체의 인터페이스를 상속함.
  • C++같이 다중 상속을 지원하는 프로그래밍 언어에서만 사용 가능 (자바는 다중상속 불가)

어디에 적용해야 할까?

  • 어댑터 클래스는 기존 클래스를 사용하고 싶지만 그 인터페이스가 나머지 코드와 호환되지 않을 때 사용하기
  • 부모 클래스에 추가할 수 없는 어떤 공통 기능들이 없는 여러 기존 자식 클래스들을 재사용하려는 경우에 사용하기
    • 누락된 기능을 어댑터 클래스에 넣고, 어댑터 내부에 누락된 기능이 있는 객체들을 래핑하면 필요한 기능들을 동적으로 얻을 것
    • 이렇게 하려면, 대상 클래스들에는 반드시 공통 인터페이스가 있어야 하며 어댑터의 필드는 해당 인터페이스를 따라야 한다 (데코레이터 패턴과 비슷)

장점

  • 단일 책임 원칙. 프로그램의 기본 비즈니스 로직에서 인터페이스 또는 데이터 변환 코드를 분리할 수 있다.
  • 개방/폐쇄 원칙. 클라이언트 코드가 클라이언트 인터페이스를 통해 어댑터와 작동하는 한, 기존의 클라이언트 코드를 손상시키지 않고 새로운 유형의 어댑터들을 프로그램에 도입할 수 있다.

단점

  • 다수의 새로운 인터페이스와 클래스들을 도입해야 하므로 코드의 전반적인 복잡성이 증가다. 때로는 코드의 나머지 부분과 작동하도록 서비스 클래스를 변경하는 것이 더 간단하다.
reference

(adpter pattern)[https://refactoring.guru/ko/design-patterns/adapter]