본문 바로가기
OOP/<헤드 퍼스트 디자인 패턴>, 에릭 프리먼 외

Facade

by 민휘 2023. 2. 24.

핵심 의도

서브 시스템에 있는 일련의 인터페이스들을 통합 인터페이스로 묶어준다. 사용에 필요한 서브 시스템 클래스만 이해하면 되고, 라이브러리 형태로 코드를 제공할 때 파사드에 포함된 클래스만 제공할 수 있으므로 코드 양이 줄어든다.

 

적용 상황

서브 시스템의 다양한 인터페이스들을 편리하게 사용하기 위해 단순화할 때 필요하다. 예를 들어 홈 씨어터를 만들어 영화를 본다면, 불을 켜고 팝콘을 튀기고 프로젝트를 켜는 등의 일련의 동작들을 ‘영화를 본다’는 하나의 인터페이스로 통합할 수 있다.

 

Decoration vs Adapter vs Facade

  • Decoration : 인터페이스는 변경하지 않고 책임만 추가하는 역할
  • Adapter : 인터페이스를 클라이언트에서 원하는 인터페이스로 바꾸는 역할
  • Facade : 클라이언트를 복잡한 서브시스템과 분리하는 역할

 

솔루션의 구조와 각 요소의 역할

객체에게 책임을 분할하기

다양한 서브시스템 클래스와 이를 사용하려는 클라이언트가 있다. 서브시스템 인터페이스를 단순화하는 책임을 가진 Facade를 둔다.

 

구현 포인트

Facade 클래스는 여러 서브시스템 클래스를 구성으로 가지며 이 클래스의 메소드를 호출한다. 이때 최소 지식 원칙을 지켜야 한다. 최소 지식 원칙에 따르면 객체 사이의 상호작용은 가능한 아주 가까운 객체들 끼리만 허용하는 것이다. 이 원칙을 지키면 시스템의 한 부분을 변경했을 때 다른 부분까지 고쳐야 하는 상황을 방지할 수 있다.

다른 객체에게 메시지를 보내는 4가지 가이드라인이다.

  1. 객체 자체
  2. 메소드에 매개변수로 전달된 객체
  3. 메소드를 생성하거나 인스턴스를 만든 객체
  4. 객체에 속하는 구성 요소

메시지로 어떤 객체를 반환 받은 다음, 그 객체에게 다른 메시지를 보내는 코드는 최소 지식 원칙을 위반한다. 호출 코드가 어떤 객체를 반환하는지 알고 있기 때문에 만약 반환 객체가 바뀐다면 이 코드도 고쳐야 한다.

 

적용 예시

요구사항

영화를 보기 위해 홈시어터 시스템을 만들었다. 영화를 보려면 팝콘을 튀기고 조명을 어둡게 조절하고 스크린을 내리고 프로젝트를 켜서 설정하고 …. 스트리밍 플레이어를 켜고 영화를 재생한다. 영화를 보기 위해 실행해야 하는 명령이 너무 많아 ‘영화를 본다’라는 간단한 명령어로 통합하려고 한다.

 

설계

코드

HomeTheaterFacade

public class HomeTheaterFacade {
	Amplifier amp;
	Tuner tuner;
	StreamingPlayer player;
	CdPlayer cd;
	Projector projector;
	TheaterLights lights;
	Screen screen;
	PopcornPopper popper;
 
	public HomeTheaterFacade(Amplifier amp, 
				 Tuner tuner, 
				 StreamingPlayer player, 
				 Projector projector, 
				 Screen screen,
				 TheaterLights lights,
				 PopcornPopper popper) {
 
		this.amp = amp;
		this.tuner = tuner;
		this.player = player;
		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.setStreamingPlayer(player);
		amp.setSurroundSound();
		amp.setVolume(5);
		player.on();
		player.play(movie);
	}
 
 
	public void endMovie() {
		System.out.println("Shutting movie theater down...");
		popper.off();
		lights.on();
		screen.up();
		projector.off();
		amp.off();
		player.stop();
		player.off();
	}

	public void listenToRadio(double frequency) {
		System.out.println("Tuning in the airwaves...");
		tuner.on();
		tuner.setFrequency(frequency);
		amp.on();
		amp.setVolume(5);
		amp.setTuner(tuner);
	}

	public void endRadio() {
		System.out.println("Shutting down the tuner...");
		tuner.off();
		amp.off();
	}
}

HomeTheaterTestDrive

public class HomeTheaterTestDrive {
	public static void main(String[] args) {
		Amplifier amp = new Amplifier("Amplifier");
		Tuner tuner = new Tuner("AM/FM Tuner", amp);
		StreamingPlayer player = new StreamingPlayer("Streaming Player", amp);
		CdPlayer cd = new CdPlayer("CD Player", amp);
		Projector projector = new Projector("Projector", player);
		TheaterLights lights = new TheaterLights("Theater Ceiling Lights");
		Screen screen = new Screen("Theater Screen");
		PopcornPopper popper = new PopcornPopper("Popcorn Popper");
 
		HomeTheaterFacade homeTheater = 
				new HomeTheaterFacade(amp, tuner, player, 
						projector, screen, lights, popper);
 
		homeTheater.watchMovie("Raiders of the Lost Ark");
		homeTheater.endMovie();
	}
}

핵심 의도

서브 시스템에 있는 일련의 인터페이스들을 통합 인터페이스로 묶어준다. 사용에 필요한 서브 시스템 클래스만 이해하면 되고, 라이브러리 형태로 코드를 제공할 때 파사드에 포함된 클래스만 제공할 수 있으므로 코드 양이 줄어든다.

적용 상황

서브 시스템의 다양한 인터페이스들을 편리하게 사용하기 위해 단순화할 때 필요하다. 예를 들어 홈 씨어터를 만들어 영화를 본다면, 불을 켜고 팝콘을 튀기고 프로젝트를 켜는 등의 일련의 동작들을 ‘영화를 본다’는 하나의 인터페이스로 통합할 수 있다.

Decoration vs Adapter vs Facade

  • Decoration : 인터페이스는 변경하지 않고 책임만 추가하는 역할
  • Adapter : 인터페이스를 클라이언트에서 원하는 인터페이스로 바꾸는 역할
  • Facade : 클라이언트를 복잡한 서브시스템과 분리하는 역할

솔루션의 구조와 각 요소의 역할

객체에게 책임을 분할하기

다양한 서브시스템 클래스와 이를 사용하려는 클라이언트가 있다. 서브시스템 인터페이스를 단순화하는 책임을 가진 Facade를 둔다.

구현 포인트

Facade 클래스는 여러 서브시스템 클래스를 구성으로 가지며 이 클래스의 메소드를 호출한다. 이때 최소 지식 원칙을 지켜야 한다. 최소 지식 원칙에 따르면 객체 사이의 상호작용은 가능한 아주 가까운 객체들 끼리만 허용하는 것이다. 이 원칙을 지키면 시스템의 한 부분을 변경했을 때 다른 부분까지 고쳐야 하는 상황을 방지할 수 있다.

다른 객체에게 메시지를 보내는 4가지 가이드라인이다.

  1. 객체 자체
  2. 메소드에 매개변수로 전달된 객체
  3. 메소드를 생성하거나 인스턴스를 만든 객체
  4. 객체에 속하는 구성 요소

메시지로 어떤 객체를 반환 받은 다음, 그 객체에게 다른 메시지를 보내는 코드는 최소 지식 원칙을 위반한다. 호출 코드가 어떤 객체를 반환하는지 알고 있기 때문에 만약 반환 객체가 바뀐다면 이 코드도 고쳐야 한다.

적용 예시

요구사항

영화를 보기 위해 홈시어터 시스템을 만들었다. 영화를 보려면 팝콘을 튀기고 조명을 어둡게 조절하고 스크린을 내리고 프로젝트를 켜서 설정하고 …. 스트리밍 플레이어를 켜고 영화를 재생한다. 영화를 보기 위해 실행해야 하는 명령이 너무 많아 ‘영화를 본다’라는 간단한 명령어로 통합하려고 한다.

설계

코드

HomeTheaterFacade

public class HomeTheaterFacade {
	Amplifier amp;
	Tuner tuner;
	StreamingPlayer player;
	CdPlayer cd;
	Projector projector;
	TheaterLights lights;
	Screen screen;
	PopcornPopper popper;
 
	public HomeTheaterFacade(Amplifier amp, 
				 Tuner tuner, 
				 StreamingPlayer player, 
				 Projector projector, 
				 Screen screen,
				 TheaterLights lights,
				 PopcornPopper popper) {
 
		this.amp = amp;
		this.tuner = tuner;
		this.player = player;
		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.setStreamingPlayer(player);
		amp.setSurroundSound();
		amp.setVolume(5);
		player.on();
		player.play(movie);
	}
 
 
	public void endMovie() {
		System.out.println("Shutting movie theater down...");
		popper.off();
		lights.on();
		screen.up();
		projector.off();
		amp.off();
		player.stop();
		player.off();
	}

	public void listenToRadio(double frequency) {
		System.out.println("Tuning in the airwaves...");
		tuner.on();
		tuner.setFrequency(frequency);
		amp.on();
		amp.setVolume(5);
		amp.setTuner(tuner);
	}

	public void endRadio() {
		System.out.println("Shutting down the tuner...");
		tuner.off();
		amp.off();
	}
}

HomeTheaterTestDrive

public class HomeTheaterTestDrive {
	public static void main(String[] args) {
		Amplifier amp = new Amplifier("Amplifier");
		Tuner tuner = new Tuner("AM/FM Tuner", amp);
		StreamingPlayer player = new StreamingPlayer("Streaming Player", amp);
		CdPlayer cd = new CdPlayer("CD Player", amp);
		Projector projector = new Projector("Projector", player);
		TheaterLights lights = new TheaterLights("Theater Ceiling Lights");
		Screen screen = new Screen("Theater Screen");
		PopcornPopper popper = new PopcornPopper("Popcorn Popper");
 
		HomeTheaterFacade homeTheater = 
				new HomeTheaterFacade(amp, tuner, player, 
						projector, screen, lights, popper);
 
		homeTheater.watchMovie("Raiders of the Lost Ark");
		homeTheater.endMovie();
	}
}

 

'OOP > <헤드 퍼스트 디자인 패턴>, 에릭 프리먼 외' 카테고리의 다른 글

Iterator  (0) 2023.02.24
Template Method  (0) 2023.02.24
Adapter  (0) 2023.02.24
Command  (0) 2023.02.24
Singleton  (0) 2023.02.24