[Java] 어댑터(Adapter) 패턴
Adapter 패턴이란
어댑터 패턴은 클래스의 인터페이스를 사용자가 기대하는 다른 인터페이스로 변환하는 패턴으로, 호환성이 없는 인터페이스 때문에 함께 동작할 수 없는 클래스들이 함께 작동하도록 해준다.
예를 들어, 실생활에서 전기 콘센트도 서로 맞지 않을 때 중간에 어댑터를 두어서 연결을 할 수 있듯이 서로 맞지 않는 두 가지 객체를 연결해 주는 역할을 하는 패턴이다.
Adapter 패턴 예시
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
- 이름과 나이 필드를 가지며 생성자와 Getter / Setter 메서드를 가지는 Person 클래스
한 가지 가정을 들어보자.
public class Main {
public static void main(String[] args) {
Person person = new Person("홍길동", 30);
System.out.println(person.getName()); // showName
System.out.println(person.getAge()); // showAge
}
}
- Person의 name과 age를 가져오기 위해 getter를 통해 가져올 수 있지만 기존에 이미 이 이름을 사용있다던지의 이유 등으로 getXXX로 가져오지 않고 다른 시스템에 있던 showName, showAge으로 이 시스템에서 사용해야한다면?
- 즉, 외부 시스템의 클래스를 사용하고 싶은데 , 클래스의 인터페이스가 다른 코드와 호환되지 않을 때 이를 해결하기 위해 어댑터를 만들어야한다.
인터페이스를 통해 역할을 정의
public interface Student {
String showName();
int showAge();
}
- showName(), showAge() 역할을 정의한다.
어댑터 역할을 하는 PersonAdapter 클래스
public class PersonAdapter implements Student {
private Person person;
public PersonAdapter(Person person) {
this.person = person;
}
@Override
public String showName() {
return person.getName();
}
@Override
public int showAge() {
return person.getAge();
}
}
- 생성자에 Person객체를 입력받아 Person필드에 주입한다.
- override를 통해 Person 객체의 name와 age 필드를 반환하도록 재정의한다.
Adapter 패턴 적용
public class Main {
public static void main(String[] args) {
Person person = new Person("홍길동", 30);
PersonAdapter personAdapter = new PersonAdapter(person);
System.out.println(personAdapter.showName()); // 홍길동
System.out.println(personAdapter.showAge()); // 30
}
}
- PersonAdapter를 통해서 Person 객체의 name, age필드를 getXXX가 아닌 showName, showAge로 반환할 수 있게 되었다.
즉, 외부 시스템(여기서는 Person)의 코드를 내부 시스템(여기서는 PersonAdapter)으로 래핑해서 원하는 결과를 얻을 수 있게 되었다. - Person(외부 시스템)이 검증된 시스템이라고 했을 때 버그가 발생하게 되면 PersonAdapter만 확인하면 된다는 장점이 있다.
Adapter 패턴 정리
어댑터 패턴은 변경할 수 없는 내부 구현이나 외부 라이브러리와의 호환성을 확보하면서 새로운 기능을 추가하거나 동작을 변경하는 상황에서 유용하게 활용할 수 있다.
라이브러리나 외부 구성 요소의 동작을 변경하는 것은 위험할 수 있으며 사이드 이펙트를 발생시킬 수 있다. 이러한 상황에서 어댑터 패턴은 기존 코드를 변경하지 않고도 원하는 동작을 추가하거나 변경할 수 있는 안정적인 방법을 제공한다.
또한, 어댑터 패턴은 재활용성과 확장 가능성을 고려할 수 있는 강력한 패턴으로 새로운 기능을 추가하기 위해 기존 코드를 수정하는 대신 어댑터를 통해 새로운 기능을 구현할 수 있으며, 기존 코드와의 결합도를 낮출 수 있다. 이는 코드 유지 보수성을 향상시키고 재사용 가능한 컴포넌트를 만들 수 있게 해준다.
물론, 어댑터 패턴은 클래스 구성 요소의 추가로 인해 복잡도가 증가할 수 있다. 따라서 적절한 상황에서 사용해야 하며, 패턴을 이해하고 적용하는 데 주의가 필요하다. 하지만 올바르게 활용된다면 어댑터 패턴은 코드를 안정적이고 확장 가능한 방식으로 구조화하는 좋은 패턴이 될 수 있다.