디자인 패턴

[디자인 패턴] 어댑터 패턴 (Adapter Pattern)

제리 . 2021. 5. 10. 20:19

어댑터 패턴이란?

어댑터 패턴은 서로 다른 인터페이스를 어탭터로 연결하여 사용할 수 있게 해주는 패턴을 말한다.

 

어댑터 패턴이 어떤 상황에서 유용한지 확인해보자.

public interface SamsungRemoteControl {

  void on();

  void off();
}

삼성리모컨 인터페이스가 있다. 

public class SamsungRemoteControlImpl implements SamsungRemoteControl {

  @Override
  public void on() {
    System.out.println("on!");
  }

  @Override
  public void off() {
    System.out.println("off!");
  }
}


삼성 리모컨은 위와 같이 동작한다.

public class Client {

  public static void main(String[] args) {
    SamsungRemoteControl remoteControl = new SamsungRemoteControlImpl();
    Refrigerator refrigerator = new Refrigerator(remoteControl);
    AirCondition airCondition = new AirCondition(remoteControl);
    refrigerator.on();
    airCondition.on();
  }
}

삼성 리모컨을 사용해서 평소 에어컨과 냉장고도 작동시키고 있었다. 

 

어느날 삼성 리모컨이 고장났다. 단종되서 더이상 생산이 불가능하단다. 집에있는 다른 리모컨을 찾던중 LG리모컨을 발견했다.

public interface LGRemoteControl {

  void on();

  void off();
}

LG리모컨의 인터페이스다. 

public class LGRemoteControlImpl implements LGRemoteControl {

  @Override
  public void on() {
    System.out.println("on!");
  }

  @Override
  public void off() {
    System.out.println("off!");
  }
}

LG리모컨은 이러한 형태로 구현되어있다.

 

그런데, 문제가 생겼다. 집안에 있는 냉장고, 에어컨등은 전부 삼성 리모컨으로 동작하게 설정되어있었다.

public class Client {

  public static void main(String[] args) {
    LGRemoteControl remoteControl = new LGRemoteControlImpl();
    Refrigerator refrigerator = new Refrigerator(remoteControl); // 컴파일 에러
    AirCondition airCondition = new AirCondition(remoteControl);// 컴파일 에러
  }
}

 

SamsungRemoteControl 인터페이스를 구현하지 않은 LGRemoteControlImpl는 삼성 냉장고와 에어컨에 사용할 수 없다.

 

그렇다면 기존에 삼성 리모컨으로 작성된 코드들을 LG리모컨의 구현체로 전부 고쳐줘야할까?

 

이때 유용하게 사용할 수 있는 방법이 어댑터 패턴이다.

public class RemoteControlAdapter implements SamsungRemoteControl {

  LGRemoteControl lgRemoteControl;

  public RemoteControlAdapter(LGRemoteControl lgRemoteControl) {
    this.lgRemoteControl = lgRemoteControl;
  }

  @Override
  public void on() {
    lgRemoteControl.on();
  }

  @Override
  public void off() {
    lgRemoteControl.off();
  }
}

어댑터에서는 LG리모컨과 삼성 리모컨의 동작을 연결시켜준다.

public class Client {

  public static void main(String[] args) {
    LGRemoteControl lgRemoteControl = new LGRemoteControlImpl();
    SamsungRemoteControl remoteControl = new RemoteControlAdapter(lgRemoteControl);
    Refrigerator refrigerator = new Refrigerator(remoteControl);
    AirCondition airCondition = new AirCondition(remoteControl);
    refrigerator.on();
    airCondition.on();
  }
}

다시 클라이언트로 돌아와서 삼성 에어컨과 냉장고를 사용할 때 LG리모컨에 어댑터를 끼워서 사용할 수 있다. 

 

정리하자면, 내가 연결하고자 하는 인터페이스를 구현한 어댑터를 만들고 메서드를 오버라이딩한다. 그리고 클라이언트 코드에서 어댑터를 연결하여 사용한다. 

 

이런 방식을 통해 얻는 장점으로 기존의 삼성 리모컨과 연관된 코드를 수정할 필요가 없다. 만약, LG리모컨이 아닌 다른 회사의 리모컨을 사용해야한다면 새롭게 어댑터 클래스를 만들어 사용해주면된다. OCP원칙을 지킬 수 있다.