어댑터(Adapter) 패턴
어댑터 패턴은 특정 클래스 인터페이스를 클라이언트에서 요구하는 다른 인터페이스로 변환한다.
인터페이스가 호환되지 않아 같이 쓸 수 없었던 클래스를 사용할 수 있게 도와준다.
어댑터 패턴을 사용하면 호환되지 않는 인터페이스를 사용하는 클라이언트를 그대로 활용할 수 있다.
이렇게 되면 클라이언트와 구현된 인터페이스를 분리할 수 있으며, 변경 내역이 어댑터에 캡슐화되기 때문에 나중에 인터페이스가 바뀌더라도 클라이언트를 바꿀 필요가 없다.
아래는 어댑터 패턴의 클래스 다이어그램이다.
예시
다음과 같은 WeatherApi
인터페이스가 있다고 하자.
// Target
public interface WeatherApi {
String getData();
}
모든 날씨 관련 API는 해당 인터페이스를 구현하여 만들어야 한다.
아래는 WeatherApi
인터페이스를 구현하여 서버 내부 데이터를 이용하여 날씨 정보를 제공하는 클래스이다.
public class InternalServerWeatherApi implements WeatherApi {
@Override
public String getData() {
return "internal server weather data";
}
}
우리 서버는 기능 확장을 위해 타 업체에서 제공하는 ExternalWeatherApi
를 사용하게 되었다.
ExternalWeatherApi
는 다음과 같은 인터페이스를 가진다.
public class ExternalWeatherApi {
public double getTemperatures() {
return 12.34;
}
public String getWind() {
return "3m/s";
}
}
우리 서버는 WeatherApi
인터페이스를 구현하여 날씨 관련 정보를 얻어야 한다는 요구사항이 있다.
그러나 타 업체에서 제공하는 ExternalWeatherApi
클래스는 우리가 원하는 인터페이스가 아니다.
해당 클래스 사용을 위해서는 기존 코드 변경이 불가피해 보인다.
이때 어댑터 패턴을 사용하면 기존 코드를 변경하지 않고 우리가 원하는 인터페이스로 ExternalWeaterApi
를 사용할 수 있게 된다.
ExternalWeatherApi
를 Adaptee
로, WeatherApi
인터페이스를 Target
으로 하는 Adapter
클래스를 만들자.
// Adapter
public class ExternalWeatherApiAdapter implements WeatherApi {
private ExternalWeatherApi externalWeatherApi;
public ExternalWeatherApiAdapter(ExternalWeatherApi externalWeatherApi) {
this.externalWeatherApi = externalWeatherApi;
}
@Override
public String getData() {
return "temp : " + externalWeatherApi.getTemperatures() + ", wind : " + externalWeatherApi.getWind();
}
}
구성을 통해 어댑터 클래스를 만들었다.
ExternalWeatherApiAdapter
는 ExternalWeatherApi
를 사용하여 WeatherApi
인터페이스를 구현한다.
이를 사용하는 Client
는 WeatherApi
로써 사용하게 된다.
public class Client {
public static void main(String[] args) {
ExternalWeatherApi externalWeatherApi = new ExternalWeatherApi();
List<WeatherApi> weatherApis = new ArrayList<>();
weatherApis.add(new InternalServerWeatherApi());
weatherApis.add(new ExternalWeatherApiAdapter(externalWeatherApi));
for (WeatherApi weatherApi : weatherApis) {
System.out.println(weatherApi.getData());
}
}
}