[7장] Adapter Pattern과 Facade Pattern

ss0510s·2022년 7월 11일
0

Adapter Pattern

특정 클래스 인터페이스를 클라이언트에게 요구하는 다른 인터페이스로 변환하는 패턴이다. 호환되지 않는 인터페이스를 사용하는 클라이언트를 그대로 활용할 수 있다.

Adpater 종류

객체 어댑터

  • Composition으로 Adapter에게 요청을 전달한다.
  • 어댑터 클래스와 그 서브 클래스에 대해서도 어댑터 역할이 가능하다.
  • Composition을 사용하여 유연하다.
  • 클라이언트는 Target에게 요청하고 있다고 생각한다.
  • 어댑터는 Target을 대상으로 하는 요청에 Adaptee 클래스도 반응할 수 있게 한다.
  • Adaptee는 Adapter에서 Target의 메소드 호출을 가로채서 Adaptee의 메소드 호출로 변환한다.

클래스 어댑터

  • Target와 Adatper 모두 서브클래스로 만들어서 사용한다.
  • 특정 어댑터 클래스에만 적용할 수 있다.
  • 어댑터 전체를 다시 구현하지 않아도 된다.
  • 클라이언트는 Target에게 요청하고 있다고 생각한다.
  • Adpater는 Target 인터페이스를 구현하지만 메소드가 호출되었을 때 그 호출을 Adaptee 메소드 호출로 변환해준다.
  • Adaptee는 Adapter를 통해 Target 인터페이스에 호출한 것을 받아 처리할 수 있다.

1장 오리 객체에 칠면조를 추가

Adaptee Interface

  • Turkey(Target) 인터페이스를 추가
public interface Turkey {
	public void gobble();
	public void fly();
}

Concrete Class

public class WildTurkey implements Turkey {
	public void gobble() {
		System.out.println("Gobble gobble");
	}
 
	public void fly() {
		System.out.println("I'm flying a short distance");
	}
}

Adapter Class

  • Turkey를 Duck 객체로 바꿀 Adapter 클래스를 생성한다.
  • Turkey 객체의 메서드를 Duck 객체의 메서드로 변환한다.
// 칠면조를 Duck으로 변환하기 위한 Adapter
public class TurkeyAdapter implements Duck {
	Turkey turkey; // Turkey 객체
 
	public TurkeyAdapter(Turkey turkey) {
		this.turkey = turkey; // 객체를 전달받음
	}
    
    // Turkey 객체의 메서드를 Duck 객체의 메서드로 변환
	public void quack() {
		turkey.gobble(); // gobble을 quack으로
	}
  
	public void fly() {
		for(int i=0; i < 5; i++) {
			turkey.fly();
		}
	}
}

Test.java

public class DuckTestDrive {
	public static void main(String[] args) {
		Turkey turkey = new WildTurkey(); // Turkey 객체 생성
		Duck turkeyAdapter = new TurkeyAdapter(turkey); // 어댑터 생성

		// Turkey 객체 수행
		System.out.println("The Turkey says...");
		turkey.gobble();
		turkey.fly();
        
        // Turkey 객체를 Duck 형태로 바꿨을 때 실행 결과
        System.out.println("\nThe TurkeyAdapter says...");
		turkeyAdapter.quack();
        turkeyAdapter.fly();

Pacade Pattern

서브시스템에 있는 일련의 인터페이스를 통합 인터페이스로 묶는 패턴이다. 고수준 인터페이스도 정의하므로 서브시스템을 더 편리하게 사용할 수 있다.

  • 단순화된 인터페이스를 제공하면서도, 클라이언트에게 필요로 한다면 시스템의 모든 기능의 사용이 가능하다.

OO 원칙

  • 최소 지식 원칙: 객체 사이의 상호작용은 될 수 있으면 아주 가까운 친구 사이에서만 허용한다. 여러 클래스가 복잡하게 얽혀있어 시스템의 한 부분을 변경했을 때, 다른 부분까지 수정해야하는 것을 미리 방지해야 한다.

최소 지식 원칙 4가지 가이드 라인

  • 객체 자체
  • 메소드에 매개변수로 전달된 객체
  • 메소드를 생성하거나 인스턴스를 만든 객체
  • 객체에 속하는 구성요소
  • 원칙을 따르지 않은 경우
    • 다른 메소드를 호출해서 리턴받는 객체의 메소드를 호출하는 일도 바람직 하지 않다.
public float getTemp() {
	// station으로 부터 thermometer 객체를 받은 다음, 그 객체의 getThermometer 메서드를 직접 호출
	Thermometer thermometer = station.getThermometer();
    return thermometer.getThermometer();
}
  • 원칙을 따르는 경우
public float getTemp() {
	// thermometer에게 요청을 전달하는 메서드를 station 클래스에 추가
    return station.getThermometer();
}

홈시어터 시스템

Facade Class

  • Client 대신 모든 서브 시스템 구성요소를 관리해 준다.
  • 클라이언트의 친구는 Facade Class 하나 뿐이다. => 최소 지식 원칙
  • 서브 시스템의 구성요소를 업그레이드해도 Client는 영향을 받지 않는다.
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();
	}
}

Test.java

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();
profile
개발자가 되기 위해 성장하는 중입니다.

0개의 댓글