[Design Pattern] Adapter Pattern

younghyun·2022년 10월 26일
0

Design Pattern

목록 보기
6/14
post-thumbnail

Adapter Pattern 이란

클래스의 인터페이스를 클라이언트가 원하는 형태의 또 다른 인터페이스로 변환하는 패턴이다.

  • 인터페이스 호환성 문제 때문에 같이 쓸 수 없는 클래스들을 연결해서 사용가능
  • 클라이언트의 변경 최소화

설계

  • Target
    : Client 가 직접적으로 사용하려고 하는 인터페이스
    : Adapter가 구현하는 인터페이스
    : 메소드에 대한 정의만 있음
interface Target {
    void operation();
}
  • Adapter
    : Client와 Adaptee 중간에서 호환성이 없는 둘을 연결시켜주는 역할
    : Target의 인터페이스를 구현하며 Adaptee의 함수 사용
// 1. 클래스에 의한 Adapter 패턴 (상속을 사용한 Adapter)
class ClassAdapter implements Target, Adaptee {

    public ClassAdapter() {
    }

    @Override
    public void operation() {
        // 상속받은 specificOperation 을 호출
        this.specificOperation();
    }

    @Override
    public void specificOperation() {
        System.out.println("this is class adapter");
    }
}

// 2. 인스턴스에 의한 Adapter 패턴 (위임을 사용한 Adapter)
class ObjectAdapter implements Target {

    Adaptee adaptee;

    public ObjectAdapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    @Override
    public void operation() {
        // 객체의 specificOperation 을 호출
        adaptee.specificOperation();
    }
}
  • Adaptee
    : 외부 라이브러리 및 외부 시스템 객체(기존 객체)
// Adaptee
interface Adaptee {
    void specificOperation();
}
class SampleAdaptee implements Adaptee {
    @Override
    public void specificOperation() {
        System.out.println("this is class adapter");
    }
}
  • Client
    : 외부 라이브러리나 시스템을 사용하려는 객체
    : Target 인터페이스를 통해 Adapter에 요청을 보냄
class Client {

    Target targetClassAdapter = new ClassAdapter();
    Target targetObjectAdapter = new ObjectAdapter(new SampleAdaptee());
    
    void execute() {
        // 클래스 adapter
        targetClassAdapter.operation();
        
        // 객체 adapter
        targetObjectAdapter.operation();
    }
}

예시 1

오리 탈을 쓴 칠면조

오리 게임에서, 오리를 잔뜩 넣어놔야 하는데 그만큼의 오리는 없고 칠면조가 있음
=> 칠면조를 오리인 것처럼 보이게 해서 넣어놓아야 함

1. Adapter Pattern 활용

TurkeyDuck으로 바꿔야 함
어댑터 도입 -> Turkey객체로 Duck의 인터페이스를 사용해야 함

  • Duck 인터페이스 상속
  • Duck 인터페이스 함수들을 오버라이딩하되, 함수 안에서 Turkey의 함수들을 호출

2. 클래스 구성

  • Target: Duck
  • Adapter: TurkeyAdapter
  • Adaptee(기존 객체): Turkey

3. 실제 구현

오리 인터페이스

public interface Duck {
          public void quack();   // 꽥꽥 울기
          public void fly();     // 날기
 }

청둥오리

public class MallardDuck implements Duck {
    public void quack(){
        System.out.println("Quack");
    }
    public void fly(){
        System.out.println("I'm flying");
    }
}

칠면조 인터페이스

public interface Turkey {
    public void gobble();   // 울기
    public void fly();     // 날기
}

야생 칠면조

public class WildTurkey implements Turkey {
    public void gobble() {
        System.out.println("Gobble gobble");
    }

    public void fly() {
        System.out.println("I'm flying a short distance");
    }
}

TurkeyAdapter (Duck을 구현)

public class TurkeyAdapter implements Duck {
    
    Turkey turkey;

    public TurkeyAdapter(Turkey turkey) {
        this.turkey = turkey;
    }
    public void quack() {
        turkey.gobble();
    }
    public void fly(){
        turkey.fly();
    }
}

Client

public class DuckTestDrive {
    public static void main(String[] args) {
    
        MallardDuck duck = new MallardDuck();
        WildTurkey turkey = new WildTurkey();
        
        // Turkey 어댑터는 Duck 타입 (Turkey 객체로 Duck 인터페이스 사용)
        Duck turkeyAdapter = new TurkeyAdapter(turkey);
        
        System.out.println("The Turkey says…");
        turkey.gobble();
        turkey.fly();
        
        System.out.println("\nThe Duck says…");
        testDuck(duck);
        
        System.out.println("\nThe TurkeyAdapter says…");
        testDuck(turkeyAdapter);
    }
    
    static void testDuck(Duck duck) {
        duck.quack();
        duck.fly();
    }
}

예시 2

Enumeration을 Iterator에 적응시키기

1. Adapter Pattern 활용

EnumerationIterator으로 바꿔야 함
어댑터 도입 -> Enumeration객체로 Iterator의 인터페이스를 사용해야 함

  • Iterator 인터페이스 상속
  • Iterator 인터페이스 함수들을 오버라이딩하되, 함수 안에서 Enumeration의 함수들을 호출

2. 클래스 구성

  • Target: Iterator
  • Adapter: EnumerationIterator
  • Adaptee(기존 객체): Enumeration

3. 실제 구현

Enumeration

Enumeration 인터페이스에서 쓰이는 메소드: hasMoreElements(), nextElement()

public class Enumeration1 {

    public static void printEnumeration(Enumeration e) {
    
        // hasMoreElements(): 뒤에 남은 데이터가 있으면 True, 없으면 False를 반환
        while (e.hasMoreElements()) {
            System.out.println("" + e.nextElement());
        }
    } 
    
    public static void main(String[] args) {
        Vector v = new Vector();
        for (int i = 0; i < 10; i++) { 
            v.add(i); 
        }
        Enumeration e = v.elements(); 
        Enumeration1.printEnumeration(e);
    }
    
}

Iterator

Iterator 인터페이스에서 쓰이는 메소드: hasNext(), next(), remove()

public class Iterator1 {

    public static void printIterator(Iterator it) {
    
        // hasNext(): 뒤에 남은 데이터가 있으면 True, 없으면 False를 반환
        while (it.hasNext()) {  
            System.out.println("" + it.next());
        }
    }
    
    public static void main(String[] args) {
        Vector v = new Vector();
        for (int i = 0; i < 10; i++) { 
            v.add(i); 
        }
        Iterator it = v.iterator();
        Iterator1.printIterator(it);
    }
}

EnumerationIterator

public class EnumerationIterator implements Iterator {

    Enumeration enumeration;
    
    public EnumerationIterator(Enumeration enmt) {
        this.enumeration = enmt;
    }
    public boolean hasNext() {
        return enumeration.hasMoreElements();
    }
    public Object next() {
        return enumeration.nextElement();
    }
    public void remove() {
        throw new UnsupportedOperationException();
    }
}

Iterator : Enumeration만 있는 것 가지고서도 만들 수 있음

public class Iterator2 {

    public static void printIterator(Iterator it) {
        while (it.hasNext()) {
            System.out.println("" + it.next());
        }
    }
    
    public static void main(String[] args) {
    
        Vector v = new Vector();
        for (int i = 0; i < 10; i++) { 
            v.add(i); 
        }
        Enumeration e = v.elements();
        EnumerationIterator it = new EnumerationIterator(e);
        Iterator2.printIterator(it);
    }
}
profile
🌱 주니어 백엔드 개발자입니당

0개의 댓글