2021. 10. 14. 18:18ㆍComputer Sciences/Design Patterns
문제
요즘 혼자 사는 사람들이 참 많아졌다. 사회적으로 불안한 요소가 많아져서 그런 듯 싶다. 나는 나중에 자취를 하게 되면 소원이 하나 있다. 바로 빔 프로젝터를 사서 집을 영화관처럼 만드는 것이다. 이를 외국에서는 홈 씨어터(Home Theater)라고 부른다. 이를 위해 여러 장비를 알아본 결과 다음과 같았다.
- 앰프
- 튜너
- CD 플레이어
- DVD 플레이어
- 프로젝터
- 스크린
- 팝콘기계
- 영화조명
이것들을 조합하여 세팅하는 것도 복잡하다. 아래는 이 장비들을 연결시킨 클래스 다이어그램이다.
보기만 해도 어지럽다. 이대로 영화를 보기 위해 순서대로 알고리즘을 짠다면 다음과 같을 것이다.
- 팝콘 기계를 켠다.
- 팝콘을 튀기기 시작한다.
- 전등을 어둡게 조절한다.
- 스크린을 내린다.
- 프로젝터를 켠다.
- 프로젝터로 DVD 신호가 입력되도록 한다.
- 프로젝터를 와이드 스크린 모드로 전환한다.
- 앰프를 켠다.
- 앰프 입력을 DVD로 전환한다.
- 앰프를 서라운드 음향 모드로 전환한다.
- 앰프 볼륨을 중간으로 맞춘다.
- DVD 플레이어를 켠단.
- 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 |