8. Facade Pattern

2021. 10. 14. 18:18Computer Sciences/Design Patterns

문제

요즘 혼자 사는 사람들이 참 많아졌다. 사회적으로 불안한 요소가 많아져서 그런 듯 싶다. 나는 나중에 자취를 하게 되면 소원이 하나 있다. 바로 빔 프로젝터를 사서 집을 영화관처럼 만드는 것이다. 이를 외국에서는 홈 씨어터(Home Theater)라고 부른다. 이를 위해 여러 장비를 알아본 결과 다음과 같았다.

 

  • 앰프
  • 튜너
  • CD 플레이어
  • DVD 플레이어
  • 프로젝터
  • 스크린
  • 팝콘기계
  • 영화조명

이것들을 조합하여 세팅하는 것도 복잡하다. 아래는 이 장비들을 연결시킨 클래스 다이어그램이다.

 

보기만 해도 어지럽다. 이대로 영화를 보기 위해 순서대로 알고리즘을 짠다면 다음과 같을 것이다.

 

  1. 팝콘 기계를 켠다.
  2. 팝콘을 튀기기 시작한다.
  3. 전등을 어둡게 조절한다.
  4. 스크린을 내린다.
  5. 프로젝터를 켠다.
  6. 프로젝터로 DVD 신호가 입력되도록 한다.
  7. 프로젝터를 와이드 스크린 모드로 전환한다.
  8. 앰프를 켠다.
  9. 앰프 입력을 DVD로 전환한다.
  10. 앰프를 서라운드 음향 모드로 전환한다.
  11. 앰프 볼륨을 중간으로 맞춘다.
  12. DVD 플레이어를 켠단.
  13. DVD를 재생한다.

대략적으로 코드로 짜면 아래 코드처럼 나온다.

popper.on();
popper.pop();

lights.dim(10);

screen.down();

projector.on();
projector.setInput(dvd);
projector.wideScreenMode();

amp.on();
amp.setDvd(dvd);
amp.setSurroundSound();
amp.setVolume(5);

dvd.on();
dvd.play(movie);

그런데 아직 끝난 게 아니다. 영화가 끝나면 실행한 순서의 반대로 종료시켜주어야 한다. 이런 것을 어떻게 해결해야 할까? 여기서 퍼사드 패턴이 빛을 발한다.

문제 해결

우리는 버튼 한 번으로 영화를 보고 뒤처리를 할 것이다.

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,
                                    TheaterLights lights,
                                    Screen screen,
                                    PopcornPopper popper) {

        this.amp = amp;
        this.tuner = tuner;
        this.dvd = dvd;
        this.cd = cd;
        this.projector = projector;
        this.lights = lights;
        this.screen = screen;
        this.popper = popper;
    }

    public void watchMovie() {

        System.out.println("Get ready to watch a movie...");
        popper.on();
        popper.pop();
        lights.dim(10);
        screen.down();
        projector.on();
        projector.setInput(dvd);
        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 HomeTheaterTest {
    // 생성자에 넣을 변수들 생성

    public static void main(String[] args) {

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

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

퍼사드 패턴이 대충 어떤 느낌인지 올 것 같다. 위 코드를 클래스 다이어그램으로 표현하면 아래와 같다. 클라이언트는 영화를 보려면 HomeTheaterFacade에서 watchMovie()endMovie()만 호출하면 된다.

 

퍼사드 패턴

어떤 서브시스템의 일련의 인터페이스에 통합된 인터페이스를 제공하는 패턴이다. 퍼사드에서 고수준 인터페이스를 정의하기 때문에 서브 시스템을 더 쉽게 사용할 수 있다. 간단하게 말하면 복잡한 과정을 추상화하는 패턴이다. 그리고 퍼사드 클래스는 단지 과정을 줄여준 것 뿐 기존 과정에 영향을 전혀 끼치지 않는다. 따라서 직접 과정을 구현하고자 하는 사람은 직접 구현하면 된다. 이 패턴에서 사용된 객체지향 원칙은 최소 지식 원칙이다.

최소 지식 원칙

객체 사이의 상호작용은 될 수 있으면 아주 가까운 친구 사이에서만 허용하는 것이 좋다는 원칙이다. 즉 정말 친한 친구하고만 이야기하라는 말이다. 좀 더 고급스럽게 설명하면 객체 사이의 연관 관계는 최소한으로 맺어야 한다는 말이다. 이 원칙을 통해 얻을 수 있는 이점은 명확하다. 여러 클래스가 서로 관계를 마구잡이로 맺고 있다면 이는 유지보수하기 매우 어려울 것이다. 따라서 연관 관계는 최소한으로 줄여야 한다는 원칙이 바로 최소 지식 원칙이다.

그렇다면 어떻게 연관 관계를 최소화 할 수 있을까? 여기에는 몇 가지 가이드라인이 있다.

 

  • 객체 자체에서 호출하기
  • 메서드에 매개변수로 전달된 객체로 호출하기
  • 그 메서드에서 생성하거나 인스턴스를 만든 객체에서 호출하기
  • 그 객체에 속하는 구성(컴포지션) 요소에서 호출하기

아래에서 원칙을 지킨 경우와 지키지 않은 경우에 대한 예시가 있다.

// 원칙을 지키지 않은 경우
public float getTemp() {
    Thermometer thermometer = station.getThermometer();
    return thermometer.getTemperature();    
}
// 원칙을 지킨 경우
public float getTemp() {
    return station.getTemperature();
}

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

10. Iterator Pattern  (0) 2021.10.15
9. Template Method Pattern  (0) 2021.10.14
7. Adapter Pattern  (0) 2021.10.14
6. Command Pattern  (0) 2021.10.14
5. Singleton Pattern  (0) 2021.09.15