본문 바로가기
Languages/디자인패턴

[Java] 어댑터(Adapter) 패턴

by yoon_seon 2023. 6. 10.

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 패턴 정리

어댑터 패턴은 변경할 수 없는 내부 구현이나 외부 라이브러리와의 호환성을 확보하면서 새로운 기능을 추가하거나 동작을 변경하는 상황에서 유용하게 활용할 수 있다.


라이브러리나 외부 구성 요소의 동작을 변경하는 것은 위험할 수 있으며 사이드 이펙트를 발생시킬 수 있다. 이러한 상황에서 어댑터 패턴은 기존 코드를 변경하지 않고도 원하는 동작을 추가하거나 변경할 수 있는 안정적인 방법을 제공한다.


또한, 어댑터 패턴은 재활용성과 확장 가능성을 고려할 수 있는 강력한 패턴으로 새로운 기능을 추가하기 위해 기존 코드를 수정하는 대신 어댑터를 통해 새로운 기능을 구현할 수 있으며, 기존 코드와의 결합도를 낮출 수 있다. 이는 코드 유지 보수성을 향상시키고 재사용 가능한 컴포넌트를 만들 수 있게 해준다.


물론, 어댑터 패턴은 클래스 구성 요소의 추가로 인해 복잡도가 증가할 수 있다. 따라서 적절한 상황에서 사용해야 하며, 패턴을 이해하고 적용하는 데 주의가 필요하다. 하지만 올바르게 활용된다면 어댑터 패턴은 코드를 안정적이고 확장 가능한 방식으로 구조화하는 좋은 패턴이 될 수 있다.

댓글