헤드퍼스트 디자인패턴
- 본 책을 읽고 책의 내용을 간략하게 정리한 글입니다.
Chapter 7. 적응시키기 - 퍼사드 패턴
예제 프로젝트 - 홈시어터 만들기
- 영화나 TV 시리즈를 몰아볼 수 있는 홈시어터를 구축해보자.
- 홈시어터에는 스트리밍 플레이어, 프로젝터, 자동 스크린, 자동 조명, 서라운드 음향, 팝콘 기계가 갖춰져 있다고 한다.
- 어떤 클래스와 어떤 메서드가 필요한 지 살펴보기
// 팝콘 기계
popper.on();
popper.pop();
// 조명
lights.dim(10);
// 스크린
screen.down();
// 프로젝터
projector.on();
projector.setInput(player);
projector.wideScreenMode();
// 서라운드 음향 (앰프)
amp.on();
amp.setDvd(player);
amp.setSurroundSound();
amp.setVolumn(5);
// 스트리밍 플레이어
player.on();
player.play(movie);
- 클래스가 6개나 필요하며, 영화를 보거나 다 보고 난 후 수행해야 할 동작들이 너무 복잡하다는 문제가 있다.
- 이런 복잡한 일을 간단하게 처리할 수 있는 게 바로 퍼사드 패턴
퍼사드 작동 원리 알아보기
- 홈시어터 시스템용 퍼사드로
watchMovie()
와 같은 몇 가지 간단한 메서드만 들어있는 HomeTheaterFacade 클래스를 만든다. - 퍼사드 클래스는 홈시어터 구성 요소를 하나의 서브시스템으로 간주하고,
watchMovie()
메서드는 서브시스템의 메서드를 호출하여 필요한 작업을 처리한다. - 클라이언트는 서브시스템이 아닌 퍼사드에 있는 메서드만 호출한다.
- 퍼사드를 사용하더라도 서브시스템에 접근 가능하다.
홈시어터 퍼사드 작성하기
public class HomeTheaterFacade {
Amplifier amp;
StreamingPlayer player;
Projector projector;
TheaterLights lights;
Screen screen;
PopcornPopper popper;
public HomeTheaterFacade(Amplifier amp,
StreamingPlayer player,
Projector projector,
TheaterLights lights,
Screen screen,
PopcornPopper popper) {
this.amp = amp;
this.player = player;
this.projector = projector;
this.lights = lights;
this.screen = screen;
this.popper = popper;
}
public void watchMovie(String movie) {
System.out.println("영화 시청 준비");
popper.on();
popper.pop();
lights.dim(10);
screen.down();
projector.on();
projector.wideScreenMode();
amp.on();
amp.setStreamingPlayer(player);
amp.setSurroundSound();
amp.setVolume(5);
player.on();
player.play(movie);
}
public void endMovie() {
System.out.println("홈시어터를 끄는 중");
popper.off();
lights.on();
screen.up();
projector.off();
amp.off();
player.stop();
player.off();
}
}
퍼사드 패턴의 정의
- 퍼사드 패턴은 서브시스템에 있는 일련의 인터페이스를 통합 인터페이스로 묶어주며, 고수준 인터페이스도 정의하므로 서브시스템을 더 편리하게 사용할 수 있다.
최소 지식 원칙
디자인 원칙 6
- 진짜 절친에게만 이야기해야 한다.
- 시스템을 디자인할 때 어떤 객체든 그 객체와 상호작용하는 클래스의 개수와 상호작용 방식에 주의를 기울여야 한다.
- 이 원칙을 잘 따르면 여러 클래스가 복잡하게 얽혀 있어서, 시스템의 한 부분을 변경했을 때 다른 부분까지 줄줄이 고쳐야 하는 상황을 미리 방지할 수 있다.
의존하지 않고 다른 객체에 영향력 행사하기
- 다음 4개의 가이드라인을 제시한다.
- 객체 자체
- 메서드에 매개변수로 전달된 객체
- 메서드를 생성하거나 인스턴스를 만든 객체
- 객체에 속하는 구성 요소
- 원칙을 따르지 않은 경우
public float getTemp() { Thermometer thermometer = station.getThermometer(); return thermometer.getTemperature(); }
- 원칙을 따르는 경우
public float getTemp() { return station.getTemperature(); }
최소 지식 원칙 예제 클래스
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() {
// 디스플레이 업데이트
}
}
퍼사드 패턴과 최소 지식 원칙
- 클라이언트는 홈시어터 퍼사드 하나에만 의존한다.
- 홈시어터 구성을 업데이트해도 클라이언트는 아무 영향을 받지 않는다.
- 서브시스템에서도 서로 얽혀 있는 객체가 많아 시스템이 복잡해진다면 퍼사드를 추가하는 것도 방법이다.