본문 바로가기
JAVA/DesignPattern

디자인패턴 - 퍼사드 패턴 (facade pattern)

by 램쥐뱅 2016. 6. 13.

퍼사드패턴 (facade pattern)


어떤 서브시스템의 일련의 인터페이스에 대한 통합된 인터페이스를 제공한다.

퍼사드에서 고수준 인터페이스를 정의하기 때문에 서브시스템을 더 쉽게 사용할수 있다.


패턴을 사용할때는 항상 패턴이 어떤 용도로 쓰이는지를 잘 알아둬야 한다.

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







홈씨어터로 퍼사드 패턴을 구현해보자.



전선과 프로젝터를 설치하고, 각 장치들을 케이블로 연결하고 등등 여러 인터페이스들이 나열되어 있다.


DVD영화를 보려고하면..

1. 팝콘 기계를켠다.

2. 팝콘 튀기기 시작.

3. 전등을 어둡게 조절

4. 스크린을 내린다.

..

..

12. DVD 플레이어를 켠다

13. DVD를 재생한다.


poper.on();

poper.pop();


light.dim(10)


screen.down();

.....

dvd.on();

dvd.play(movie);


이런식으로 된다면..

영화를 끄려면 방금 했던 일을 전부 역순으로 해야하는가?

CD나 라디오를 들을 때도 복잡한가?

시스템이 업그레이드 되면 또 다른 작동 방법을 배워야 하는가?

같은 홈 씨어터 사용법이 너무 복잡해진다.



이런 경우에 퍼사드를 사용하면 된다.


퍼사드 패턴은 인터페이스를 단순화시키기 위해서 인터페이스를 변경한다.

때문에 훨씬 쓰기 쉬운 인터페이스를 제공하는 퍼사드 클래스를 구현함으로써 복잡한 시스템을 훨씬 쉽게 사용할 수 있다.




HomeTheaterFacade를 만들어 보자

                                         

 public class HomeTheaterFacade {

           Amplifier amp;

           Tuner tuner;

           Dvdplayer dvd;

           CdPlayer cd;

           Projector projector;

           TheaterLights lights;

           Screen screen;

           PopcornPopper popper;


           public HomeTheaterFacade( Amplifier amp,

                                                Tuner tuner, 

                                                DvdPlayer dvd,

                                                CdPlayer cd,

                                                Projector projector,

                                                Screen screen,

                                                TheaterLights lights,

                                                PopcornPopper popper) {

                    this.amp = amp;

                    this.tunner = tuner;

                    this.dvd = dvd;

                    this.cd = cd;

                    this.projector = projector;

                    this.screen = screen;

                    this.lights = lights;

                    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();

                    projector.wideScreenMode();

                    amp.on();

                    amp.setDvd(dvd);

                    amp.setsurroundSound();

                    amp.setVolume(5);

                    dvd.on();

                    dvd.play(movie);

          }


          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();

          }


 }



public class HomeTheaterTestDrive {

         public static void main(String[] args) {

                    // instantiate components here

                    HomeTheaterFacade homeTheater  =

                               new HomeTheaterFacade(amp, tuner, dvd, cd, projector, screen, lights, popper);

                    homeTheater.watchMovie("타짜");

                    homeTheater.endMovie();


          }

}



어떤 서브시스템에 속한 일련의 복잡한 클래스들을 단순화 하고 통합한 클래스를 만들어 퍼사드 패턴을 완성하였다.

이제 클라이언트와 서브시스템이 서로 긴밀하게 연결되지 않아도 되고. 최소 지식 원칙 을 준수하는데도 도움을 준다.




최소 지식 원칙.


정말 친한 친구하고만 얘기하라.


어떤 객체든 그 객체와 상호작용을 하는 클래ㅡ의 개수에 주의해야 하며,

그런 객체들과 어떤 식으로 상호작용을 하는지에도 주의를 기울여야 한다는 뜻이다.


어떻게 하면 여러 객체하고 인연을 맺는 것을 피할 수 있을까??


어떤 메소드에서든지 아래와 같은 네 종류의 객체의 메소드만을 호출하면 된다.


1. 객체 자체

2. 메소드에 매개변수로 전달된 객체

3. 그 메소드에서 생성하거나 인스턴스를 만든 객체

4. 그 객체에 속하는 구성요소



원칙을 따르지 않은 경우


public float getTemp() {

          Thermometer thermometer = station.getThermometer(); // station 오로부터 thermometer라는 객체를 받은다음

          return thermometer.getTemperature();                           그 갹체의 getTemperature()메소드를 직접 호출.

}


원칙을 따르는 경우


public float getTemp() {

         return station.getTemperature(); // Station 클래스에 thermometer에 요청을 해주는 메소드를 추가

                                                            이렇게 하면 의존해야 하는 클래스의 개수를 줄일수 있다.

}


예를들면.


public class Car {

           Engine engine; //이 클래스의 구성요소. 이 구성요소의 메소드는 호출해도 된다.


           public Car() { }


           public void start(Key key) { // 매개변수로 전달된 객체의 메소드는 호출해도 된다.

                     Doors doors = new Doors(); //새로운 객체 생성. 이 객체의 메소드는 호출해도 된다.


                     boolean authorized = key.turns(); //매개변수로 전달된 객체의 메소드는 호출해도 된다.

     

                     if ( authorized ) { 

                               engine.start(); // 이 객체의 구성요소의 메소드는 호출해도 된다.

                               updateDashboardDisplay(); // 객체 내에 있는 메소드는 호출해도 된다.

                               doors.lock(); //직접 생성하거나 인스턴스를 만든 객체의 메소드는 호출해도 된다.

                     }

           }


           public void updateDashboardDisplay() { }

 }









참고.


Head First Design Pattern.

댓글