[헤드퍼스트 디자인패턴] 07. 어댑터 패턴(Adapter Pattern)과
퍼사드 패턴(Facade Pattern)
1. 어댑터 패턴
1.1 어댑터 패턴이란?
특정 클래스 인터페이스를 클라이언트에서 요구하는 다른 인터페이스로 변환한다. 인터페이스가 호환되지 않아 같이 쓸 수 없었던 클래스를 사용할 수 있게 도와준다.
어떤 소프트웨어 시스템에서 새로운 업체에서 제공한 인터페이스가 기존에 사용하던 인터페이스와 다를 때, 어댑터를 사용해 문제를 해결할 수 있다.
1.2 어댑터 사용 방법 알아보기
오리 인터페이스와 구현 클래스를 작성한다.
public interface Duck {
public void quack();
public void fly();
}
public class MallardDuck implements Duck {
@Override
public void quack() {
System.out.println("Quack");
}
@Override
public void fly() {
System.out.println("I'm flying");
}
}
칠면조 인터페이스와 구현 클래스를 작성한다.
public interface Turkey {
public void gobble();
public void fly();
}
public class WildTurkey implements Turkey {
@Override
public void gobble() {
System.out.println("gobble gobble"); // 칠면조는 골골거린다.
}
@Override
public void fly() {
System.out.println("I'm flying a short distance"); // 칠면조도 날 순 있지만, 멀리 날 수 없다.
}
}
오리 객체가 모자라서 칠면조 객체를 대신 사용해야하는 상황일 때, 인터페이스가 다르므로 칠면조 객체를 바로 사용할 수는 없기 때문에 어댑터를 만들어야 한다.
public class TurkeyAdapter implements Duck{
Turkey turkey;
public TurkeyAdapter(Turkey turkey){
this.turkey = turkey;
}
@Override
public void quack() {
turkey.gobble();
}
@Override
public void fly() {
for(int i=0; i<5; i++){
turkey.fly();
}
}
}
오리 객체가 필요하기 때문에 adapter에 오리를 상속해 형식을 맞춰주고 어댑터 생성자로 칠면조를 주입받아 실제로는 칠면조 메소드를 호출해서 사용한다.
오리 어댑터 테스트용 코드
public class MainTest {
public static void main(String[] args) {
MallardDuck duck = new MallardDuck();
WildTurkey turkey = new WildTurkey();
Duck turkeyAdapter = new TurkeyAdapter(turkey);
System.out.println("칠면조가 말하길");
turkey.gobble();
turkey.fly();
System.out.println("오리가 말하길");
testDuck(duck);
System.out.println("칠면조 어댑터가 말하길");
testDuck(turkeyAdapter);
}
static void testDuck(Duck duck) {
duck.quack();
duck.fly();
}
}
1.3 어댑터 패턴의 특징
- 호환되지 않는 인터페이스를 사용하는 클라이언트를 그대로 활용할 수 있다.
- 클라이언트와 구현된 인터페이스를 분리할 수 있다.
- 객체 구성을 사용하므로 어댑티의 모든 서브클래스에 어댑터를 쓸 수 있다.
2. 퍼사드 패턴
2.1 퍼사드 패턴 이란?
서브시스템에 있는 일련의 인터페이스를 통합 인터페이스로 묶어 준다. 고수준 인터페이스도 정의하므로 서브시스템을 더 편리하게 사용할 수 있다.
2.2 퍼사드 패턴 사례
집에 홈시어터를 만든다고 가정하자. 홈시어터를 만들기 위해서는 아래와 같은 수많은 객체가 필요하다.
영화를 보려면 아래와 같은 일을 해야한다.
popper.on();
popper.pop();
lights.dim(10);
screen.down();
projector.on();
projector.setInput(player);
projector.wideScreenMode();
amp.on();
amp.setDvd(player);
amp.setSurroundSound();
amp.setVolume(5);
dvd.on();
dvd.play(movie);
그렇다면 영화가 끝나면 방금 했던 일을 역순으로 처리해야 할까?
라디오를 들을때도 이렇게 복잡할까?
시스템을 업그레이드하면 작동 방법을 또 배워야 할까?
-> 이런 복잡한 일을 퍼사드 패턴으로 간단하게 처리할 수 있다.
2.3 퍼사드 구현
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,
Screen screen,
TheaterLights lights) {
this.amp = amp;
this.tuner = tuner;
this.dvd = dvd;
this.cd = cd;
this.projector = projector;
this.screen = screen;
this.lights = lights;
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.setDvd(dvd);
amp.setSurroundSound();
amp.setVolume(5);
dvd.on();
dvd.play(movie);
}
public void endMovie() {
System.out.println("홈시어터 끄는 중...");
popper.off();
lights.on();
screen.up();
projector.off();
amp.off();
dvd.stop();
dvd.eject();
dvd.off();
}
}
이렇게 퍼사드 객체를 별도로 구성하면 퍼사드 메소드를 호출하기만 하면 된다.
public class HomeTheaterTestDrive {
public static void main(String[] args) {
// 구성 요소 초기화
HomeTheaterFacade homeTheater =
new HomeTheaterFacade(amp, tuner, dvd, cd, projector, screen, lights, popper);
homeTheater.watchMovie("인디아나 존스:레이더스");
homeTheater.endMovie();
}
}
퍼사드 패턴은 단순화된 인터페이스로 서브 시스템을 더 편리하게 사용하려고 쓰인다.
'스터디 > 헤드퍼스트 디자인패턴' 카테고리의 다른 글
[헤드퍼스트 디자인패턴] 08. 반복자 패턴 (Iterator Pattern) 과 컴포지트 패턴 (Composite Pattern) (0) | 2022.07.31 |
---|---|
[헤드퍼스트 디자인패턴] 08. 템플릿 메소드 패턴(Template method) (0) | 2022.07.24 |
[헤드퍼스트 디자인패턴] 06. 커맨드 패턴(Command Pattern) (0) | 2022.07.10 |
[헤드퍼스트 디자인패턴] 05. 팩토리 패턴(Factory Pattern) (1) | 2022.07.03 |
[헤드퍼스트 디자인패턴] 04. 싱글턴 패턴(Singleton Pattern) (0) | 2022.06.18 |
댓글