본문 바로가기
스터디/헤드퍼스트 디자인패턴

[헤드퍼스트 디자인패턴] 07. 어댑터 패턴(Adapter Pattern)과 퍼사드 패턴(Facade Pattern)

by 디토20 2022. 7. 17.
반응형

 

 

[헤드퍼스트 디자인패턴] 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();
    }
}

 

퍼사드 패턴은 단순화된 인터페이스로 서브 시스템을 더 편리하게 사용하려고 쓰인다.

 

 

 

728x90
반응형

댓글