어댑터 패턴

이정석·2023년 5월 24일
0

디자인패턴

목록 보기
3/23

어댑터 패턴이란?

GoF의 구조패턴으로 분류되었고 클래스의 인터페이스를 클라이언트가 원하는 대로 변경할 수 있는 패턴이다. 어댑터 패턴은 호환 불가능한 인터페이스를 때문에 협력할 수 없는 클래스들을 협력할 수 있게 한다.


문제상황

1. 다음과 같은 Client와 서비스를 제공하는 Service클래스가 있다고 하자.

class Service {
    void service(char[] data) {
        System.out.println("Called service");
    }
}

public class Client {
    public static void main(String[] args) {
    	String _input="Input Data";
    
        Service service = new Service();
        char[] charData = _input.toCharArray();
        adapter.request(charData);
    }
}

Client를 보면 입력값(_input)을 char[]로 변환하고 Service의 service메소드를 호출한다.

2. 여기서 수정사항이 생기거나 예기치 못한 상황으로 Service클래스가 아닌 다음과 같은 OtherService클래스를 사용한다고 하자.

class OtherService {
    void request(List<Character> data) {
        System.out.println("Called request");
    }
}

3. Service클래스 대신 OtherService를 사용한다면 Client코드는 다음과 같이 바뀌어야 한다.

public class Client {
    public static void main(String[] args) {
    	String _input="Input Data";
    
        OtherService otherservice = new OtherService();
        List<Character> charList = new ArrayList<>();
        for (char c : _input.toCharArray()) {
            charList.add(c);
        }
        adapter.request(charList);
    }
}

Service가 바뀌었을 때 Client의 코드가 바뀌는 상황이다. 이는 Client와 Service사이의 높은 결합이 형성되어 있다는 뜻이다. Service의 함수명이나 매개변수 타입과 같이 작은것들이 바뀌면 Client의 코드에 영향이 미친다는 것이다.

  • Client의 크기가 크다면 Service가 바뀔때마다 Client를 다시 컴파일 해야할 것이고 이는 시간이 오래 걸릴 것이다.
  • 문제의 원인은 Client와 Service사이의 호환이 맞지 않는다는 것

    두 개의 클래스 사이에 호환을 담당하는 클래스를 둔다면?
    이후 Service를 담당하는 객체가 바뀌어도 Client대신 호환을 담당하는 클래스를 바꾸면 된다!


구조

  1. AdapterInterface: Client가 의존할 Adapter의 인터페이스
  2. Adapter: AdpaterInterface를 구현하고 Adaptee에 넘겨줄 데이터를 재가공하거나 클라이언트가 접근하고자 하는 함수명을 바꾸어 주는 클래스
  3. Adaptee: 실제 기능을 제공하는 클래스로 주로 다른 모듈이나 레거시시스템을 의미한다.

코드(JAVA)

1. AdapterInterface

interface AdapterInterface {
    void request(String data);
}

2. Adapter

class Adapter implements AdapterInterface {
    private Adaptee adaptee;

    public Adapter(Adaptee a) {
        this.adaptee = a;
    }

    public void request(String data) {
        char[] charData = data.toCharArray();
        adaptee.specificFunction(charData);
    }
}

3. Adaptee

class Adaptee {
    void specificFunction(char[] specificdata) {
        System.out.println("Called specificFunction");
    }
}

Adaptee를 다른 클래스로 교체하거나 char[]를 List로 바꿔도 Adapter의 request()만 수정하면 된다.

즉, Client는 Adaptee의 변경에 아무런 영향을 받지 않는다.


위임을 통한 구현

위 코드를 보면 Apdater 클래스에서 adaptee라는 객체를 가지고 있고 함수 호출을 통해 메시지를 전달하는데 이것을 위임이라 한다.

private Adaptee adaptee;
  • 상속을 이용하면 안되나?
    상속을 이용하면 Adaptee의 내부구현을 알아야 한다. 물론 함수를 오버라이딩을 하거나 내부 데이터를 활용할 수 있지만, JAVA와 같이 다중상속이 불가능한 상황이 있을 수 있기 때문에 위임을 사용하는것이 대부분 좋다.
profile
게임 개발자가 되고 싶은 한 소?년

0개의 댓글