참치코더의 꿈 메모장

디자인 패턴 / 어댑터 패턴 정리 본문

디자인 패턴

디자인 패턴 / 어댑터 패턴 정리

참치깡 2025. 10. 3. 14:18
728x90

 

 

어댑터 패턴

 

- 어댑터 패턴은 호환되지 않는 인터페이스를 가진 클래스를 클라이언트가 원하는 인터페이스로 

  변환해 주는 구조적 디자인 패턴이다.

 

필요한 이유

 

- 이미 있는 라이브러리/레거시 코드와 새 코드의 인터페이스가 다를 때

- 외부 API가 제공하는 시그니처를 바꾸지 못할 때

- 클라이언트 코드는 변경하지 않고도, 다른 구현을 끼워 넣고 싶을 때

 

어댑터 패턴을 사용하는 2가지 방법

 

- Object Adapter (조합 방식)

  : 어댑터가 Adaptee 인스턴스를 가지고 Target 인터페이스 구현, 대부분의 언어에서 권장되는 방식

 

- Class Adapter (상속 방식)

: 어댑터가  Adaptee를 상속하고 Target을 구현하는 방식, 다중 상속이 가능한 언어에서만 완전하게 지원한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// Target: 클라이언트가 원하는 인터페이스
 
public interface Target {
    void request();
}
 
// Adaptee: 기존에 있던, 호환 안 되는 클래스
 
public class Adaptee {
    public void specificRequest(){
        System.out.println("Adaptee: specificRequest()");
    }
}
 
// Adapter: Target을 구현하고 Adaptee에 위임(조합)
 
public class Adapter implements Target {
    private final Adaptee adaptee;
 
    public Adapter(Adaptee adaptee){
        this.adaptee = adaptee;
    }
 
    @Override
    public void request(){
        // 변환(어댑트) 작업
        System.out.println("Adapter: translating request() to specificRequest()");
        adaptee.specificRequest();
    }
}
 
// client
 
public class Client {
    public static void main(String[] args){
        Adaptee adaptee = new Adaptee();
        Target adapter = new Adapter(adaptee);
        adapter.request();
    }
}
 
// 사용자는 Target만 알고 있고, 실제 동작은 Adapter가 동작한다...
 
 
cs

 

장점

 

- 기존 코드 변경 없이 통합 가능

- 단일 책임, 변환 로직이 어댑터에 집중됨

 

단점

 

- 어댑터가 너무 많아지면 복잡해짐

- 성능상 오버헤드와 의미상 변환 오류 가능성이 있다.

 

스프링 MVC의 HandlerAdapter

 

- 스프링 MVC 구조에서 메인 기능은 어댑터 패턴으로 개발이 되어있다.

 

- 보통 다양한 형태의 컨트롤러 (@Controller의 메서드, HttpRequestHandler, SimpleController)

  를 불러와서 해당 컨트롤러의 기능을 사용할 수 있도록 하는데에 어댑터 패턴이 사용된다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// Target 인터페이스
 
public interface PaymentGateway {
    boolean pay(int amount);
}
 
// Adaptee (외부 라이브러리 - 회사 레거시 결제 시스템 가정)
 
public class LegacyPaymentSystem {
    public void makePayment(double dollars){
            System.out.println("Paid $" + dollars);
    }
}
 
// Adapter
public class LegacyPaymentAdapter implements PaymentGateway {
    private final LegacyPaymentSystem legacy;
 
    public LegacyPaymentAdapter(LegacyPaymentSystem legacy) {
        this.legacy = legacy;
    }
 
    // 새로운 결제 시스템 코드 메서드 오버라이드 및 레거시 시스템 활용
    @Override
    public boolean pay(int amount) {
        double dollars = amount / 100.0;
        legacy.makePayment(dollars);
        return true;
    }
}
 
 
// 사용
@RestController
@RequiredArgsConstructor
public class PaymentController {
    private final PaymentGateway paymentGateway;
 
    @PostMapping("/pay")
    public String pay(@RequestParam int amount) {
        paymentGateway.pay(amount);
        return "ok";
    }
}
cs
728x90
Comments