1. 어댑터 패턴
어댑터 디자인 패턴은 기존 클래스의 인터페이스를 다른 인터페이스로 사용할 수 있도록 하는 구조 패턴이다. 호환되지 않는 두 인터페이스를 연결하여 함께 작동하도록 하는 다리 역할을 한다. 이 패턴에는 독립적이거나 호환되지 않는 인터페이스의 기능을 결합하는 역할을 하는 Adapter 라는 단일 클래스가 포함된다. 이름은 어댑터(Adapter) 외에도 래퍼(Wrapper) 로 명명되기도 한다.
2. 어댑터 패턴 구성 요소
- Target interface
- 설명 : 클라이언트가 기대하는 인터페이스를 정의한다. 클라이언트 코드가 사용할 수 있는 연산 집합을 나타낸다.
- 역할 : 클라이언트 코드가 상호 작용하는 공통 인터페이스 이다.
- Adaptee
- 설명: 새 시스템에 통합해야 하는 호환되지 않는 인터페이스가 있는 기존 클래스 또는 시스템이다.
- 역할: 인터페이스 불일치로 인해 클라이언트 코드가 직접 사용할 수 없는 클래스 또는 시스템이다.
- Adapter
- 설명: 대상 인터페이스를 구현하고 내부적으로 어댑터의 인스턴스를 사용하여 대상 인터페이스와 호환되도록 하는 클래스이다.
- 역할: 어댑터의 인터페이스를 대상 인터페이스와 일치하도록 조정하는 브리지 역할을 한다.
- Client
- 설명: 대상 인터페이스를 사용하여 객체와 상호 작용하는 코드입니다. adaptee 와 adapter 의 구체적인 구현 세부 사항은 알지 못합니다.
- 역할: adapter 를 통해 시스템에 adaptee 를 통합함으로써 이점을 얻는 코드이다.
3. 어댑터 패턴이 필요한 경우
- 기존 코드 통합
- 시나리오: 새 코드나 시스템에서 기대하는 인터페이스와 호환되지 않는 인터페이스를 가진 기존 코드나 컴포넌트가 있는 경우.
- 필요: 어댑터 패턴을 사용하면 원래 코드를 수정하지 않고도 기존 컴포넌트를 새 시스템에 원활하게 통합할 수 있다.
- 기존 기능 재사용
- 시나리오 : 중요한 기능을 제공하지만 원하는 인터페이스에 맞지 않는 클래스나 컴포넌트를 재사용하려는 경우.
- 필요 : 어댑터 패턴을 사용하면 새 코드에서 기대하는 인터페이스와 호환되는 어댑터를 만들어 기존 코드를 재사용할 수 있다.
- 상호 운용성
- 시나리오: 서로 다른 시스템이나 구성 요소가 함께 작동하도록 해야 할 때, 특히 인터페이스가 서로 다른 경우.
- 필요성: 어댑터 패턴은 호환되지 않는 인터페이스를 가진 시스템이 효과적으로 협업할 수 있도록 다리 역할을 한다.
4. 어댑터 패턴은 지양하는 경우
- 인터페이스가 안정적인 경우
- 시나리오: 기존 시스템과 새 시스템의 인터페이스가 안정적이고 자주 변경될 것으로 예상되지 않는 경우.
- 이유: 어댑터는 진화하거나 호환되지 않는 인터페이스를 다룰 때 가장 유용하다.
- 직접 수정이 가능한 경우
- 시나리오: 기존 시스템의 소스 코드를 제어할 수 있고 대상 인터페이스와 일치하도록 인터페이스를 직접 수정할 수 있는 경우.
- 이유: 기존 코드를 수정할 수 있다면 어댑터를 도입하는 것보다 인터페이스를 직접 적용하는 것이 더 간단하고 간단한 해결책이다.
- 여러 개의 어댑터가 필요한 경우
- 시나리오: 시스템에 다양한 구성 요소를 위한 수많은 어댑터가 필요하고 이러한 어댑터를 관리하는 것이 너무 복잡해지는 경우.
- 이유: 많은 수의 어댑터를 관리하면 복잡성이 증가하고 유지 관리 문제가 발생할 수 있습니다.
- 어댑터가 모호성을 유발하는 경우
- 시나리오: 어댑터를 도입하여 전체 시스템 아키텍처에 모호함이나 혼란을 초래하는 경우
- 이유: 어댑터의 존재로 인해 시스템 설계가 명확하지 않거나 이해하기 어려울 수 있다.
5. 어댑터 패턴의 장점
- 장점
- 기존 코드를 변경하지 않고 원하는 인터페이스 구현체를 만들어 재사용할 수 있다. (OCP 충족)
- 기존 코드가 하던 일과 특정 인터페이스 구현체로 변환하는 작업을 각기 다른 클래스로 분리하여 관리할 수 있다.
- 단점
- 새 클래스가 생겨 복잡도가 증가할 수 있다. 경우에 따라서는 기존 코드가 해당 인터페이스를 구현하도록 수정하는 것이 좋은 선택일 수 있다.
6. 의사코드 & 구현 코드
sample code (출처 : refactoring.guru)
- 둥근 구멍들에 정사각형 못들을 맞추기 가능한지 확인하기
public class Demo {
public static void main(String[] args) {
// client
RoundHole hole = new RoundHole(5);
// target
RoundPeg rpeg = new RoundPeg(5);
if (hole.fits(rpeg)) {
System.out.println("Round peg r5 fits round hole r5.");
}
// adaptee
SquarePeg smallSqPeg = new SquarePeg(2);
SquarePeg largeSqPeg = new SquarePeg(20);
// adapter
SquarePegAdapter smallSqPegAdapter = new SquarePegAdapter(smallSqPeg);
SquarePegAdapter largeSqPegAdapter = new SquarePegAdapter(largeSqPeg);
if (hole.fits(smallSqPegAdapter)) {
System.out.println("Square peg w2 fits round hole r5.");
}
if (!hole.fits(largeSqPegAdapter)) {
System.out.println("Square peg w20 does not fit into round hole r5.");
}
}
}
7. 어댑터 패턴 예시
- java
- Arrays.asList, Collections.list
- java.io package : InputStreamReader, BufferedStreamReader
- spring
- HandlerAdapter
'java > summary' 카테고리의 다른 글
Virtual Thread 무엇일까? summary (0) | 2024.11.28 |
---|---|
자바 비동기로 카페 콘솔 예제 만들기 (1) | 2024.11.26 |
퍼사드 패턴(Facade Pattern) (0) | 2024.07.08 |
커맨드 패턴(command pattern) (0) | 2024.07.08 |
책임 연쇄 패턴 (chain of responsibility pattern) (1) | 2024.07.05 |