헤드퍼스트 디자인 패턴 7장 | 적응시키기 - 어댑터 패턴과 퍼사드 패턴
(에릭 프리먼 외 4인, 서환수 옮김, 한빛미디어)
객체지향 어댑터도 일상생활에서 쓰이는 어댑터와 똑같은 역할을 합니다. 어떤 인터페이스를 클라이언트에서 요구하는 형태로 적응시키는 역할을 하죠.
- 272p
public class TurkeyAdapter implements Duck {
Turkey turkey;
public TurkeyAdapter(Turkey turkey) {
this.turkey = turkey;
}
public void quack() {
turkey.gobble();
}
public void fly() {
for(int i=0; i < 5; i++) {
turkey.fly();
}
}
=> 우선 적응시킬 형식의 인터페이스를 구현해야 합니다. 다시 말해, 클라이언트에서 원하는 인터페이스를 구현해야 하죠.
=> 그리고 기존 형식 객체의 레퍼런스가 필요합니다. 여기서는 생성자에서 레퍼런스를 받아오는 작업을 처리합니다.
=> 인터페이스에 들어있는 메소드를 모두 구현해야 합니다.
quack()은 간단합니다. 그냥 gobble() 메소드를 호출하면 되죠.
=> 두 인터페이스 모두 fly()가 들어있지만 5번 호출 => 좀 더 멀리 움직이도록
- 275p
public class DuckTestDrive {
public static void main(String[] args) {
Duck duck = new MallardDuck();
Turkey turkey = new WildTurkey();
Duck turkeyAdapter = new TurkeyAdapter(turkey);
=> Turkey 객체를 TurkeyAdapter로 감싸서 duck 객체처럼 보이도록 만듭니다.
- 276p
어댑터 패턴은 특정 클래스 인터페이스를 클라이언트에서 요구하는 다른 인터페이스로 변환합니다. 인터페이스가 호환되지 않아 같이 쓸 수 없었던 클래스를 사용할 수 있게 도와줍니다.
- 279p
퍼사드 패턴 맛보기
이제부터 조금 다른 이유로 인터페이스를 변경하는 패턴을 알아보겠습니다. 이 패턴은 인터페이스를 단순하게 바꾸려고 인터페이스를 변경하죠. 이 패턴의 이름은 퍼사드 패턴입니다. 하나 이상의 클래스 인터페이스를 깔끔하면서도 효과적인 퍼사드(facade)로 덮어 주거든요.
- 290p
퍼사드는 인터페이스를 단순하게 만들고 클라이언트와 구성 요소로 이루어진 서브시스템을 분리하는 역할도 합니다. 퍼사드와 어댑터는 모두 여러 개의 클래스를 감쌀 수 있습니다. 하지만 퍼사드는 인터페이스를 단순하게 만드는 용도로 쓰이는 반면, 어댑터는 인터페이스를 다른 인터페이스로 변환하는 용도로 쓰입니다.
- 296p
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;
}
watchMovie() 메소드와 영화가 끝난 후 사용하는 endMovie() 메소드를 구현
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);
}
=> watchMovie() 메소드는 앞에서 일일이 수동으로 했던 작업을 순서대로 처리합니다.
꽤 복잡한 일을 하나의 메서드로 간단하게 처리할 수 있죠.
각 작업은 서비시스템에 들어있는 구성 요소에게 위임됩니다.
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) {
- 296 ~ 298p
최소 지식 원칙에 따르면 객체 사이의 상호작용은 될 수 있으면 아주 가까운 '친구' 사이에서만 허용하는 편이 좋습니다. 이 원칙은 보통 다음과 같이 정의할 수 있습니다.
디자인 원칙 : 진짜 절친에게만 이야기해야 한다.
- 301p
원칙을 따르지 않은 경우
public float getTemp() {
Thermomter thermometer = station.getThermometer();
return thermometer.getTemperature();
}
=> station으로부터 thermometer 객체를 받은 다음, 그 객체의 getTemperature() 메소드를 직접 호출합니다.
원칙을 따르는 경우
public float getTemp() {
return station.getTemperature();
}
=> 최소 지식 원칙을 적용해서 thermometer에게
요청을 전달하는 메소드를 station 클래스에 추가했습니다.
이러면 의존해야 하는 클래스의 개수를 줄일 수 있죠.
- 302p
절친에게만 메소드 호출하기
public class Car {
Engine engine;
=> 이 클래스의 구성 요소
이 구성요소의 메소드는 호출해도 되죠.
public Car() {
// 엔진 초기화 등을 처리
}
public void start(Key key) { => 매개 변수로 전달받은 객체의 메소드는 호출해도 됩니다.
Doors doors = new Doors(); => 새로운 객체 생성
boolean authorized = key.turfns(); => 매개 변수로 전달받은 객체의 메소드
if (authorized) {
engine.start() => 객체 내의 구성 요소 호출 가능
updateDashboardDisplay(); => 객체 내의 메소드 호출 가능
doors.lock(); => 직접 생성하거나 인스턴스를 만든 객체의 메소드 호출 가능
=
}
}
public void updateDashBoardDisplay() {
// 디스플레이 갱신
}
}
- 303p
'Book' 카테고리의 다른 글
[독서 기록] 헤드퍼스트 디자인 패턴 9장 | 컬렉션 잘 관리하기 - 반복자 패턴과 컴포지트 패턴 (0) | 2022.11.15 |
---|---|
[독서 기록] 헤드퍼스트 디자인 패턴 8장 | 알고리즘 캡슐화하기 - 템플릿 메소드 패턴 (0) | 2022.11.15 |
[독서 기록] 헤드퍼스트 디자인 패턴 6장 | 커맨트 패턴 - 호출 캡슐화하기 (0) | 2022.11.15 |
[독서 기록] 헤드퍼스트 디자인 패턴 5장 | 싱글턴 패턴 - 하나뿐인 특별한 객체 만들기 (0) | 2022.11.15 |
[독서 기록] 헤드퍼스트 디자인 패턴 4장 | 팩토리 패턴 - 객체지향 빵 굽기 (0) | 2022.11.14 |