_ 개발

[DESIGN PATTERN/JAVA] Adapter - 어댑터 패턴

옴뇽뇽 2024. 11. 11. 13:33

목 차

Adapter : 바꿔서 재이용하기

Adapter 패턴의 구성 요소

Adapter 패턴의 구현 예시

Adapter 패턴의 특징

Adapter : 바꿔서 재이용하기

기존 클래스의 인터페이스를 다른 인터페이스로 변환하여, 호환성이 없는 클래스들을 사용할 수 있도록 만들어 주는 패턴이다. 일상 생활에서도 이러한 Adapter의 적용은 쉽게 찾아볼 수 있다. 외국으로 여행갈 때, 표준전압이 우리나라(220V)와 다른 나라면 전자기기를 충전하기 위해서 멀티 플러그 어댑터를 챙겨야한다. 또, 충전 단자가 USB C타입인 최신 전자기기 전용 충전기를 구매하지 않고, 기존 충전기를 그대로 사용하기 위해 USB A to C 변환 젠더를 사용하기도 한다.
 
이와 같이 Adapter 패턴을 사용하면 기존 코드를 변경하지 않고도 호환성 문제를 해결할 수 있다. 기존 클래스의 인터페이스가 새롭게 적용하려고 하는 인터페이스와 호환되지 않을 때, 외부 라이브러리의 인터페이스를 변경하지 않고 사용하고자 할 때 유용한 패턴이다. 

 


Adapter 패턴의 구성 요소 

Adapter 패턴은 주로 클래스에 의한 Adapter객체에 의한 Adapter, 이 두 가지 방식으로 구현된다. 

클래스에 의한 Adapter 패턴 다이어그램
클래스에 의한 Adapter 패턴 다이어그램
인스턴스(객체)에 의한 Adapter 패턴 다이어그램
인스턴스(객체)에 의한 Adapter 패턴 다이어그램

1. Target

  • 클라이언트가 실제 사용할 메서드가 속한 클래스

2. Client

  • 실제 호출(사용)하는 곳

3. Adaptee

  • Target과 호환되지 않은 다른 메서드가 구현된 클래스 
  • Adaptee의 메서드가 Target의 메서드와 일치 하다면 Adapter가 필요하지 않음

4. Adapter

  • Target 메서드들과 대응되는 Adaptee 메서드들을 변환(adapt) 시켜줌

Adapter 패턴의 구현 예시

이 패턴의 예제에서는는 텍스트 편집기에서 문자열 좌우에 별표({}) 또는 물결표(~~)를 붙여 출력하는 프로그램인 Banner를 구현해 볼 예정이다. 이 두가지 방식으로 구현할 때, 다음과 같이 구성된다.

1. 클래스(상속)에 의한 Adapter

클래스에 의한 Adapter 패턴 다이어그램
클래스에 의한 Adapter 패턴 다이어그램

 
(1) Banner 클래스

public class Banner {
    private String string;

    public Banner(String string) {
        this.string = string;
    }

    public void showWithAstarisk() {
        System.out.println("*" + string + "*");
    }

    public void showWithTilds() {
        System.out.println("~~" + string + "~~");
    }
}
  • 문자열 좌우에 괄호를 붙이거나 별표를 붙여 출력하기 위한 클래스다.
  • showWithhAstarisk 메서드 : 문자열을 인수로 전달받아 좌우에 별표를 붙여 화면에 출력한다. → *Hello* 
  • showWithTildes 메서드 : 문자열을 인수로 전달받아 좌우에 물결표를 붙여 화면에 출력한다. → ~~Hello~~

(2) Print 인터페이스

public interface Print {
    public abstract void printItalic();
    public abstract void printCancelLine();
}
  •  Banner를 필요한 형태로 변환 시켜준다.

(3) PrintBanner 클래스

public class PrintBanner extends Banner implements Print {
    public PrintBanner(String string) {
        super(string);
    }

    @Override
    public void printItalic() {
        showWithAstarick();
    }

    @Override
    public void printCancelLine() {
        showWithTildes();
    }
}
  • Banner를 상속 받아 Print 인터페이스를 구현하여 이용 가능하게 해줄 어댑터이다.
  • printItalic 메서드 : Banner에서 상속 받은 showWithAstarisk 메서드를 사용하여 별표에 쌓인 문자열 출력한다.
  • printCancelLine 메서드 : Banner에서 상속 받은 showWithTildes 메서드를 사용하여 물결표에 쌓인 문자열 출력한다.

 

2. 객체(위임)에 의한 Adapter

Banner 클래스는 동일하게 구현되며, Print는 추상클래스로 변경 한다.

객체에 의한 Adapter 패턴 다이어그램
객체에 의한 Adapter 패턴 다이어그램

 
(1) PrintBanner 클래스

public class PrintBanner extends Print {
    private Banner banner;

    public PrintBanner(String string) {
        this.banner = new Banner(string);
    }

    @Override
    public void printItalic() {
        banner.showWithAstarisk();
    }

    @Override
    public void printCancelLine() {
        banner.showWithTildes();
    }
}
  • Print 클래스를 상속 받아 printItalic과 printCancelLine 메서드 구현한다.
  • Banner 인스턴스(객체)를 생성자의 인스턴스로 받아 멤버 변수 필드 banner에 저장한다.
  • printItalic, printCancelLine 메서드 내의 로직 처리를 각각 banner의 showWithAstarisk, showWithTildes 메서드를 호출에 처리하므로서 역할을 banner에게 위임한다.

클라이언트에서 실행

public class Main {
    public static void main(String[] args) {
        Print p = new PrintBanner("Hello");
        p.printItalic();
        p.printCancelLine();
    }
}
  • 어댑터인 PrintBanner 인스턴스를 사용하여 Hello 문자열을 출력한다.
  • 사용자(Client)는 어탭터의 printItalic나 printCancelLine 사용법만 알고 있으면 된다.

Adapter 패턴의 특징

재활용성과 유지보수성

  • 기존 클래스를 활용하여 현재에 필요에 맞는 클래스를 생성하여 사용한다.
  • 기존 코드는 변경하지 않고 새 인터페이스에 맞출 수 있어 재사용성이 높아진다.

호환성과 유연성

  • 여러 클래스를 쉽게 호환성 있게 사용할 수 있으며, 외부 라이브러리의 클래스와 연동하기에 유리하다.

Ref.

  • 책 『JAVA 언어로 배우는 디자인 패턴 입문: 쉽게 배우는 GoF의 23가지 디자인 패턴』 (저자 : 유키 히로시 저 / 번역 : 김성훈 역, 영진닷컴)
  • https://jh-bk.tistory.com/50