Adapter 패턴

목차

디자인 패턴은 개발 과정 중 문제 해결/요구사항 처리하는 효과적인 방식을 패턴화한 것이다. 스프링 디자인 패턴은 상속/인터페이스/컴포지션(객체를 속성으로 사용)을 사용한다.

어댑터 패턴이란

  🌟 어떤 클래스에 사용자가 원하는 인터페이스를 구현하게 하고 싶을 떄 사용한다. 어댑터 클래스를 통해 새 인터페이스를 구현하게 한다.

대표적인 예시로 JDBC가 있다. JDBC는 다양한 DBMS를 구현체만 바꾸어 사용하는 공통 인터페이스이다. Oravcle, MySQL은 연관성이 없지만, JDBC 인터페이스를 통해 호환 가능하다. 그리고 일관되게 동작한다.

사용하는 이유?

  1. 연관없는 클래스들끼리 공통 인터페이스를 구현하여, 일관되게 동작하게 한다. 또한, 공통 인터페이스를 통해 클래스들끼리 호환할 수 있다. 이로 인해 클라이언트 코드가 간단해진다.

  2. 이미 구현된 라이브러리에 새 기능을 추가하고 싶을 경우, 기존 코드를 변경하지 않고 새로운 인터페이스(기능)를 구현하게 한다.

동작 (JDBC 예시)

기존 클래스(Adaptee)가 새로운 인터페이스(Target)를 구현하고 싶은 상황

  1. 클라이언트는 Target 인터페이스(JDBC)에 의존한다.

  2. 이 Target 인터페이스를 Adapter 클래스가 구현한다.

  3. Adapter 클래스가 Adaptee 인스턴스를 감싼다. 이로 인해 Adaptee 인스턴스는 Target 인터페이스를 구현한다.

  4. 기존 클래스들, 즉 Adaptee 클래스들(Oracle/MySQL JDBC Driver)은 Target 인터페이스(JDBC)의 메소드들을 각자에 맞게 오버라이딩한다.

따라서 Adaptee 클래스들(Oracle/MySQL JDBC Driver)은 서로 연관성이 없지만, 일관되게 동작한다. 또한 클라이언트는 Target 인터페이스에만 의존하므로, 필요에 따라 Adaptee 를 바꿔 사용할 수 있다.

예시

예시 참고 : Bird를 구현한 Sparrow는 새롭게 ToyDuck의 기능을 구현하고 싶은 상황.

  1. SparrowBird인터페이스를 구현하는 클래스이다. (Sparrow 이 새로운 인터페이스 ToyDuck을 구현하고 싶은 상황)

interface Bird
{
    public void fly();
    public void makeSound();
}
  
class Sparrow implements Bird
{
    public void fly()
    {
        System.out.println("Flying");
    }
    public void makeSound()
    {
        System.out.println("Chirp Chirp");
    }
}
  1. SparrowToyDuck인터페이스를 구현하게 하고 싶으므로, Adapter 패턴을 사용한다. ToyDuck인터페이스를 구현한 Adapter 클래스를 생성한다.

interface ToyDuck
{
    // target interface
    public void squeak();
}

// 어댑터 클래스
class BirdAdapter implements ToyDuck
{
    Bird bird;
    public BirdAdapter(Bird bird)
    {
        this.bird = bird; // adaptee
    }
  
    public void squeak()
    {
        bird.makeSound();
    }
}
  1. BirdAdapter 객체에 Sparrow 를 주입한다. (어댑터 객체에 기존 객체를 주입한다.) ⇒ SparrowToyDuck 기능도 가진다.

Sparrow sparrow = new Sparrow();

// sparrow을 birdAdapter로 감싸서(주입해서)
// ToyDuck의 동작을 수행하게 한다.
ToyDuck birdAdapter = new BirdAdapter(sparrow);

Adapter로 감싸지는 AdapteeTarget 인터페이스를 사용할 수 있다. 이러한 방식으로 Adapter 패턴을 사용하면 연관없는 클래스들도 공통 인터페이스(Target )를 가지게된다. 또한 코드 변경없이 원하는 인터페이스를 상속받게 한다.

Reference

Last updated