본문 바로가기

JAVA/Design Patterns

7.어댑터 패턴 / 퍼사드 패턴

반응형

어댑터 패턴


데코레이터 패턴은 객체를 래퍼로 감싸서 새로운 역할을 부여함

다른 목적으로 객체를 감싼다.

실제와 다른 인터페이스를 가진 것처럼


기존시스템에서 새로운 업체에서 제공한 클래스 라이브러리를 사용해야한다고 하면, 사용하는 인터페이스가 기존 업체에서 사용하던 인터페이스가 다르다.

기존코드를 바꿔서 해결할 수 없는 상황일경우, 업체에서 공급받은 클래스도 변경할 수 없다면?

새로 사용하기로 한 업체에서 사용하는 인터페이스를 기존에 사용하던 인터페이스에 적응시켜주는 클래스를 만들 수 있다.

어댑터는 클라이언트로부터 요청을 받아서 새로운 업체에서 제공하는 클래스에서 받아들일 수 있는 형태의 요청으로 변환시켜주는 중개인 역할을 한다.




예)


package patterns.adaptor;


public interface Duck {

    void quack();

    void fly();

}


package patterns.adaptor;


public class MallardDuck implements Duck{

    @Override

    public void quack() {

        System.out.println("Quack");

    }

    @Override

    public void fly() {

        System.out.println("far fly");

    }

}




package patterns.adaptor;


public interface Turkey {

    void gobble();

    void fly();

}


package patterns.adaptor;


public class WildTurkey implements Turkey{

    @Override

    public void gobble() {

        System.out.println("Gobble gobble");

    }

    @Override

    public void fly() {

        System.out.println("short fly");

    }

}



package patterns.adaptor;


public class TurkeyAdapter implements Duck {

    private Turkey turkey;

    

    public TurkeyAdapter(Turkey turkey) {

        this.turkey = turkey;

    }

    @Override

    public void quack() {

        turkey.gobble();

    }

    @Override

    public void fly() {

        turkey.fly();

    }

}




package patterns.adaptor;


public class DuckTestDriven {

    public static void main(String[] args) {

        MallardDuck duck = new MallardDuck();

        WildTurkey turkey = new WildTurkey();

        Duck turkeyAdapter =  new TurkeyAdapter(turkey);


        System.out.println("The Turkey says...");

        turkey.gobble();

        turkey.fly();


        System.out.println("The Duck says...");

        testDuck(duck);


        System.out.println("The TurkeyAdapter says...");

        testDuck(turkeyAdapter);

    }


    private static void testDuck(Duck duck) {

        duck.quack();

        duck.fly();

    }

}


사용방법

1. 클라이언트에서 타켓 인터페이스를 사용하여 메서드를 호출함으로써 어댑터에 요청을 한다.

2. 어댑터에서는 어탭티 인터페이스를 사용하여 그 요청을 어댑티에 대한 (하나 이상의) 메서드 호출로 변환한다.

3. 클라이언트에서는 호출 결과를 받기 하지만 중간에 어탭터가 껴 있는지 전혀 알지 못한다.



어댑터 패턴의 정의

- 한 클래스의 인터페이스를 클라이언트에서 사용하고자 하는 다른 인터페이스로 변환한다.

어댑터를 이용하면 인터페이스 호환성 문제 때문에 같이 쓸수 없는 클래스들을 연결해서 쓸 수 있다.


객체 어댑터

-> 어댑터를 새로 바뀐 인터페이스로 감쌀때는 객체구성을 사용한다. 어댑티의 어떤 서브클래스에 대해서도 어댑터를 쓸수 있는 장점이 있다.



클래스 어댑터

-> 다중 상속이 필요한데, 자바에서는 다중 상속이 불가. 다중상속이 가능한 언어를 사용하는 경우에도 클래스 어댑터를 써야하는 경우가 생길수도 있다.



예)

package patterns.adaptor;


import java.util.Enumeration;

import java.util.Iterator;


public class EnumerationIterator implements Iterator {

    Enumeration enumeration;


    public EnumerationIterator(Enumeration enumeration) {

        this.enumeration = enumeration;

    }


    @Override

    public void remove() {

        throw new UnsupportedOperationException();

    }


    @Override

    public boolean hasNext() {

        return enumeration.hasMoreElements();

    }


    @Override

    public Object next() {

        return enumeration.nextElement();

    }

}



퍼사드 패턴
어댑터 패턴에서 어떤 클래스의 인터페이스를 클라이언트에서 원하는 인터페이스로 변환하는 방법으로 호환성이 없는 인터페이스를 가지고 있는 객체를 올바른 인터페이스를 구현하는 객체로 감싸서 어댑터 패턴을 구현 함.
다른 이유로 인터페이스를 변경하는 패턴으로 인터페이스를 단순화시키기 위해 인터페이스를 변경한다.
하나 이상의 클래스의 복잡한 인터페이스를 깔끔하면서도 퍼사드로 덮어주는 퍼사드 패턴

정의
- 어떤 서브시스템의 일련의 인터페이스에 대한 통합된 인터페이스를 제공한다.
퍼사드에서 고수준 인터페이스를 정의하기 때문에 서브시스템을 더 쉽게 사용할 수 있다.

단순화된 인터페이스를 통해서 서브시스템을 더 쉽게 사용할 수 있도록 하기 위한 용도로 쓰임.




예) 홈시어터

package patterns.facade;

public class HomeTheaterFacade {
    Amplifier amp;
    Tuner tuner;
    DvdPlayer dvd;
    Projector projector;
    Screen screen;
    TheaterLights lights;
    PopcornPopper  popper;


    public HomeTheaterFacade(Amplifier amp,
                             Tuner tuner,
                             DvdPlayer dvd,
                             Projector projector,
                             Screen screen,
                             TheaterLights lights,
                             PopcornPopper popper) {
        this.amp = amp;
        this.tuner = tuner;
        this.dvd = dvd;
        this.projector = projector;
        this.lights = lights;
        this.screen = screen;
        this.popper = popper;
    }

    public void watchMovie(String movie) {
        System.out.println("get ready to watch a movie");
        popper.on();
        popper.pop();
        lights.dim(10);
        screen.down();
        projector.on();
        amp.on();
        amp.setDvd(dvd);
        amp.setVoulume();
        dvd.on();
        dvd.play();
    }

    public void endMovie() {
        System.out.println("Shutting movie theater down...");
        popper.off();
        lights.on();
        screen.up();
        projector.off();
        amp.off();
        dvd.stop();
        dvd.eject();
        dvd.off();

    }

}

package patterns.facade;

public class HomeTheaterTestDriven {
    public static void main(String[] args) {
        Amplifier amp = new Amplifier();
        Tuner tuner = new Tuner();
        DvdPlayer dvdPlayer = new DvdPlayer();
        Projector projector = new Projector();
        Screen screen = new Screen();
        TheaterLights lights = new TheaterLights();
        PopcornPopper popper = new PopcornPopper();

        HomeTheaterFacade homeTheater
                = new HomeTheaterFacade(amp, tuner, dvdPlayer, projector, screen, lights, popper);

        homeTheater.watchMovie("Avatar");
        homeTheater.endMovie();
    }
}

핵심정리
- 기존 클래스를 사용하고 하는데 인터페이스가 맞지 않으면 어댑터를 쓰면된다.
- 큰 인터페이스 또는 여러 인터페이스를 단순화 시키거나 통합시켜야 되는 경우에는 퍼사드 패턴을 쓰면된다.
- 어댑터는 인터페이스를 클라이언트에서 원하는 인터페이스로 바꿔주는 역할을 한다.
- 퍼사드는 클라이언트를 복잡한 서브시스템과 분리시켜주는 역할을 한다.
- 어댑터를 구현할때는 타겟 인터페이스의 크기와 구조에 따라 코딩해야 할 분량이 결정된다.
- 퍼사드 패턴에서는 서브시스템을 가지고 퍼사드를 만들고 실제 작업은 서브클래스에 맡긴다.
- 어댑터 패턴에는 객체 어댑터와 클래스 어댑터가 있다. 클래스 어댑터를 쓰려면 다중 상속 기능이 필요하다.
- 한 서브시스템에 퍼사드를 여러개 만들어도 된다.
- 어댑터는 객체를 감싸서 인터페이스를 바꾸기 위한 용도로, 데코레이터는 객체를 감싸서 새로운 행동을 추가하기 위한 용도로, 퍼사드는 일련의 객체들을 감싸서 단순화시키기 위한 용도로 쓰인다.

출처 - Head First Design Patterns 저자- 에릭 프리먼, 엘리자베스 프리먼, 케이시 시에라, 버트 베이츠


반응형

'JAVA > Design Patterns' 카테고리의 다른 글

9.이터레이터 패턴  (0) 2018.12.13
8.템플릿 메서드 패턴  (0) 2018.12.10
6.커맨드 패턴  (0) 2018.12.06
5. 싱글톤 패턴  (0) 2018.12.06
4. 팩토리 메서드 패턴 / 추상 팩토리 패턴  (0) 2018.12.05