어댑터 패턴

심야·2022년 11월 16일
0

웹 개발

목록 보기
18/46

어댑터 패턴(Adapter Pattern)

어댑터를 번역하면 변환기라 할 수 있다. 변환기 역할은 서로 다른 두 인터페이스 사이에 통신이 가능하게 하는 것이다. 예를 들면 충전기가 대표적인 변환기이다. 휴대폰을 직접 전원 콘센트에 연결할 수 없으므로 충전기가 핸드폰과 전원 콘센트 사이에서 둘을 연결해주는 변환기 역할을 수행한다. 따라서 어댑터 패턴은 호환되지 않는 인터페이스를 가진 객체들이 협업할 수 있도록 하는 구조적 디자인 패턴이다.

Example

둥근 구멍들에 정사각형 못들을 맞추는 예제이다. 호환되지 않는 객체들이 어댑터를 활용해 서로 협업할 수 있도록 하는지 보여준다.

RoundHole.java (둥근 구멍)

public class RoundHole {
    private double radius;

    public RoundHole(double radius){
        this.radius = radius;
    }

    public double getRadius(){
        return radius;
    }

    public boolean fits(RoundPeg peg){
        boolean result;

        result = (this.getRadius() >= peg.getRadius());
        return result;
    }
}

RoundPeg.java (둥근 못들)

public class RoundPeg{
    private double radius;

    public RoundPeg(){}

    public RoundPeg(double radius){
        this.radius = radius;
    }

    public double getRadius(){
        return radius;
    }
}

SquarePeg.java (정사각형 못들)

public class SquarePeg {
    private double width;

    public SquarePeg(double width){
        this.width = width;
    }

    public double getWidth(){
        return width;
    }

    public double getSquare(){
        double result;
        result = Math.pow(this.width, 2);
        return result;
    }
}

SquarePegAdapter.java (정사각형 못들을 둥근 구멍들에 맞추는 어댑터)

// Adapter allows fitting square pegs into round holes.
public class SquarePegAdapter extends RoundPeg{
    private SquarePeg peg;

    public SquarePegAdapter(SquarePeg peg){
        this.peg = peg;
    }

    @Override
    public double getRadius(){
        double result;
        // Calculate a minimum circle radius, which can fit this peg
        result = (Math.sqrt(Math.pow((peg.getWidth() / 2), 2) * 2));
        return result;
    }
}

Demo.java 클라이언트 코드

public class Demo {
    public static void main(String[] args) {
        // Round fits round, no surprise
        RoundHole hole = new RoundHole(5);
        RoundPeg rpeg = new RoundPeg(5);
        if(hole.fits(rpeg)){
            System.out.println("Round peg r5 fits round hole r5.");
        }

        SquarePeg smallSqPeg =new SquarePeg(2);
        SquarePeg largeSqPeg = new SquarePeg(20);
        // hole.fits(smallSqPeg); Won't compile.

        // Adapter solves the problem
        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 w20 does not fit into round hole r5.");
        }
    }
}

실행 결과

Round peg r5 fits round hole r5.
Square peg w2 fits round hole r5.
Square w20 does not fit into round hole r5.

어댑터를 사용해 정사각형 못을 정사각형 지름의 절반을 반지름으로 가진 둥근 못인 척 한다.

적용 예시

  1. 어댑터 클래스는 기존 클래스를 사용하고 싶지만 그 인터페이스가 나머지 코드와 호환되지 않을 때 사용한다.
  2. 어댑터 패턴은 코드와 레거시 클래스, 타사 클래스 또는 특이한 인터페이스가 있는 다른 클래스 간 변환기 역할을 하는 중간 레이어 클래스를 만들 수 있다.
  3. 상위 클래스에 추가할 수 없고 어떤 공통 기능들이 없는 여러 기존 하위 클래스들을 재사용할 때 사용한다.
  4. 하위 클래스를 확장한 후 누락된 기능을 어댑터 클래스에 넣는다. 그 후 어댑터 내부에 누락된 기능이 있는 객체들을 래핑하면 필요한 기능들을 동적으로 얻을 수 있다. 이 경우 대상 클래스들은 반드시 공통 클래스가 있어야 하며 어댑터 필드는 해당 인터페이스를 따라야 한다.

장단점

  1. 단일 책임 원칙. 프로그램 기본 비즈니스 로직에서 인터페이스 또는 데이터 변환 코드를 분리할 수 있다.
  2. 개방/폐쇄 원칙. 클라이언트 코드가 클라이언트 인터페이스를 통해 어댑터와 작동하는 한, 기존 클라이언트 코드를 손상시키지 않고 새로운 유형 어댑터들을 프로그램에 도입할 수 있다.
  3. 다수의 새로운 인터페이스와 클래스들을 도입해야 해 코드의 전반적인 복잡성이 증가한다. 때로는 코드의 나머지 부분과 작동하도록 서비스 클래스를 변경하는 것이 더 간단할 수 있다.

출처

디자인 패턴에 뛰어들기
스프링 입문을 위한 자바 객체 지향의 원리와 이해

profile
하루하루 성실하게, 인생 전체는 되는대로.

0개의 댓글