1. 정의
- 어댑터 패턴은 서로 다른 인터페이스를 가진 클래스들이 호환되도록 도와주는 구조적 디자인 패턴.
- 클라이언트가 기대하는 인터페이스와 기존 클래스의 인터페이스가 다를 때, 이를 변환해주는 어댑터 클래스를 사용
2. 목적
- 호환되지 않는 인터페이스를 통합.
- 기존 코드를 변경하지 않고 새로운 시스템과 호환되도록 만듦.
3. 주요 구성 요소
- 클라이언트(Client): 어댑터를 통해 변환된 인터페이스를 사용하려는 대상.
- 어댑터(Adapter): 기존 시스템의 인터페이스와 클라이언트가 기대하는 인터페이스를 연결하는 클래스.
- 타겟(Target): 클라이언트가 기대하는 인터페이스.
- 어댑티(Adaptee): 호환되지 않는 인터페이스를 가진 기존 클래스.
4. 예시
- 전기 어댑터: 한국(220V)과 미국(110V) 전압 차이를 해결해주는 어댑터.
- 소프트웨어에서의 어댑터 패턴:
- 구형 시스템과 새로운 시스템의 인터페이스가 다를 때, 어댑터 클래스를 사용하여 호환성 문제를 해결.
5. 구현 코드
5.1 Animal (타겟 인터페이스)
public abstract class Animal {
public abstract String getName();
}
5.2 Doorman (클라이언트)
public class Doorman {
public void 쫓아내(Animal animal) {
System.out.println(animal.getName() + " 쫓아내");
}
}
5.3 Cat, Mouse (어댑티)
public class Cat extends Animal {
private String name = "고양이";
public String getName() {
return name;
}
}
public class Mouse extends Animal {
private String name = "쥐";
public String getName() {
return name;
}
}
5.4 OuterTiger (외부 라이브러리)
public class OuterTiger {
private String fullname = "호랑이";
public String getFullname() {
return fullname;
}
}
5.5 TigerAdapter (어댑터)
public class TigerAdapter extends Animal {
private OuterTiger outerTiger;
public TigerAdapter(OuterTiger outerTiger) {
this.outerTiger = outerTiger;
}
@Override
public String getName() {
return outerTiger.getFullname(); // OuterTiger의 getFullname()을 getName()으로 변환
}
}
5.6 App (클라이언트 실행)
public class App {
public static void main(String[] args) {
Doorman doorman = new Doorman();
OuterTiger outerTiger = new OuterTiger();
TigerAdapter ta = new TigerAdapter(outerTiger);
Mouse mouse = new Mouse();
Cat cat = new Cat();
// Doorman이 각 동물을 쫓아냄
doorman.쫓아내(ta); // TigerAdapter를 통해 OuterTiger 쫓아냄
doorman.쫓아내(cat); // 고양이 쫓아냄
doorman.쫓아내(mouse); // 쥐 쫓아냄
}
}
5.7 출력 결과
💡 호랑이 쫓아내
고양이 쫓아내
쥐 쫓아내
6. 장점
- 유연성: 기존 코드 변경 없이 새로운 시스템과 통합 가능.
- 재사용성: 기존 코드를 재사용하면서 새로운 요구 사항에 맞춤.
- 클린 코드: 인터페이스 변환 로직을 어댑터에 캡슐화하여 클라이언트 코드 간결.
7. 단점
- 추가 클래스: 어댑터 클래스를 추가해야 하므로 코드 복잡성 증가.
- 성능 오버헤드: 어댑터를 사용하면서 약간의 성능 저하가 있을 수 있음.
Share article