110V 전자제품을 220V 콘센트에 꽂을 때 변환 어댑터를 쓴다. 제품도, 콘센트도 바꾸지 않고 중간에 어댑터만 끼우면 된다. 코드에서도 똑같은 상황이 생긴다.
서로 호환되지 않는 인터페이스를 함께 동작할 수 있게 변환해주는 패턴이다. 기존 코드를 수정하지 않고, 중간에 어댑터 클래스를 하나 두어 연결한다.
외부 라이브러리나 레거시 코드를 내 시스템에 맞게 붙여야 할 때 자주 쓰인다.

상황: 내 시스템은 JsonParser 인터페이스를 기대하는데, 외부 라이브러리는 XmlReader만 제공한다.
// 내 시스템이 기대하는 인터페이스
public interface JsonParser {
String parse(String data);
}
// 외부 라이브러리 — 수정 불가
public class XmlReader {
public String readXml(String xmlData) {
return "XML parsed: " + xmlData;
}
}
// 어댑터 — XmlReader를 JsonParser처럼 쓸 수 있게 감쌈
public class XmlToJsonAdapter implements JsonParser {
private XmlReader xmlReader;
public XmlToJsonAdapter(XmlReader xmlReader) {
this.xmlReader = xmlReader;
}
@Override
public String parse(String data) {
// XmlReader의 메서드를 호출해서 JsonParser 형식으로 변환
String xmlResult = xmlReader.readXml(data);
return "{ \"result\": \"" + xmlResult + "\" }";
}
}
// 사용하는 쪽 — JsonParser만 알면 됨
JsonParser parser = new XmlToJsonAdapter(new XmlReader());
String result = parser.parse("<name>김자바</name>");
System.out.println(result);
XmlReader도 바꾸지 않고, 내 JsonParser 인터페이스도 바꾸지 않았다. 어댑터만 추가했을 뿐이다.
Java 표준 라이브러리에서도 Adapter를 볼 수 있다.
// Arrays.asList() — 배열을 List로 변환하는 어댑터
String[] arr = {"a", "b", "c"};
List<String> list = Arrays.asList(arr);
// InputStreamReader — InputStream을 Reader로 변환하는 어댑터
Reader reader = new InputStreamReader(System.in);
InputStreamReader는 바이트 스트림(InputStream)을 문자 스트림(Reader)으로 변환한다. 전형적인 Adapter 구조다.
Adapter는 기존 코드를 건드리지 않는다. 호환되지 않는 두 쪽 사이에 끼어들어 번역만 해준다. 변경 범위를 최소화하면서 연결해야 할 때 꺼내 쓰면 된다.