본문 바로가기
Design Pattern/구조 패턴(Structural Patterns)

어댑터(Adapter) 패턴 - 구조 패턴 (Structural Patterns)

by 김 민 준 2024. 5. 16.

 

어댑터 패턴은 두개의 서로 호환되지 않는 인터페이스를 가진 클래스들이 함께 동작 할 수 있도록 중간에 어댑터 역할을 하는 클래스를 두는 디자인 패턴이다.

 

간단한 예시로는 전기 어댑터를 살펴보면 좋다.

 

한국에서는 220V 콘센트를 사용하는데 미국에서는 110V콘센트를 사용한다. 이때 한국에서 가지고간 220V 전자 제품을 미국에서 사용하고 싶다면 어댑터를 사용하는것이다.

 

// V220Socket 인터페이스: 220V 소켓
public interface V220Socket {
    void connect();
}

 

// V220Appliance 클래스: 220V 전자 기기
public class V220Appliance implements V220Socket {
    @Override
    public void connect() {
        System.out.println("Connected to 220V power supply.");
    }
}

 

// V110Socket 인터페이스: 110V 소켓
public interface V110Socket {
    void plugIn();
}

 

// V110Appliance 클래스: 110V 전자 기기
public class V110Appliance implements V110Socket {
    @Override
    public void plugIn() {
        System.out.println("Connected to 110V power supply.");
    }
}

 

// Adapter110To220 클래스: 110V 소켓을 220V 소켓으로 변환하는 어댑터
public class Adapter110To220 implements V220Socket {
    private V110Socket v110Socket;

    public Adapter110To220(V110Socket v110Socket) {
        this.v110Socket = v110Socket;
    }

    @Override
    public void connect() {
        // V110Socket의 plugIn 메서드를 호출하여 변환
        v110Socket.plugIn();
    }
}

 

// 사용 예시
public class AdapterPatternDemo {
    public static void main(String[] args) {
        // 110V 전자 기기와 어댑터를 생성합니다.
        V110Socket v110Appliance = new V110Appliance();
        V220Socket adapter = new Adapter110To220(v110Appliance);

        // 어댑터를 사용하여 110V 기기를 220V 소켓에 연결합니다.
        adapter.connect();  // 출력: Connected to 110V power supply.
    }
}

 

예제 소스 코드를 보면 Adapter110To220을 이용하여 v110을 변환하고 있는것을 볼 수 있다. 

 

이렇게 아답터 패턴은 과거의 시스템과 새로운 시스템을 변환할때 사용하는 경우가 많다. 

 

레거시 결제 시스템을 사용하려 할때의 예제소스코드를 살펴보자.

 

// 새 결제 시스템 인터페이스
public interface NewPaymentSystem {
    void processPayment(double amount);
}

// 레거시 결제 시스템
public class LegacyPaymentSystem {
    public void makePayment(double amount) {
        System.out.println("Processing payment of $" + amount + " through legacy system.");
    }
}

// 어댑터 클래스
public class LegacyPaymentAdapter implements NewPaymentSystem {
    private LegacyPaymentSystem legacyPaymentSystem;

    public LegacyPaymentAdapter(LegacyPaymentSystem legacyPaymentSystem) {
        this.legacyPaymentSystem = legacyPaymentSystem;
    }

    @Override
    public void processPayment(double amount) {
        legacyPaymentSystem.makePayment(amount);
    }
}

// 사용 예시
public class AdapterPatternDemo {
    public static void main(String[] args) {
        LegacyPaymentSystem legacyPayment = new LegacyPaymentSystem();
        NewPaymentSystem paymentAdapter = new LegacyPaymentAdapter(legacyPayment);

        paymentAdapter.processPayment(100.0);  // 출력: Processing payment of $100.0 through legacy system.
    }
}

 

단순한 예제 소스코드이지만 실무에서도 비슷하게 구현한다. 

 

결과적으로 어댑터 패턴은 시스템을 통합하거나, 레거시 코드 호환성을 유지하거나 서로 다른 API를 사용하는 시스템간에 통합하는데 유용하다. 만약에라도 시스템에 문제가 생겨 레거시 코드를 사용해야 하는데 레거시 코드를 모두 지우고 새로 구현만 했다면 장애시간이 길어져 끔찍한 현실을 마주할 것이다.