The Adapter and Facade Patterns

2023. 10. 21. 23:17디자인패턴

728x90

Adapter

나에게 있던 기존의 소프트웨어와 구입한 소프트웨어가 맞지 않을 때

둘 사이를 이어주는 역할을 한다.

-> 기존의 소프트웨어를 수정하지 않고 사용할 수 있도록 한다.

 

 

 

코드

public interface Duck {
    public void quack();
    public void fly();
}
public class MallardDuck implements Duck {
    public void quack() {
    	System.out.println(“Quack”);
    }
    public void fly() {
    	System.out.println(“I’m flying”);
    }
}
public interface Turkey {
    public void gobble();
    public void fly();
}
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”);
    }
}
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();
    	}
    }
}
public class DuckTestDrive {
    public static void main(String[] args) {
        MallardDuck duck = new MallardDuck();
        WildTurkey turkey = new WildTurkey();
        Duck turkeyAdapter = new TurkeyAdapter(turkey);
        
        System.out.println(“The Turkey says...”);
        turkey.gobble();
        turkey.fly();
        
        System.out.println(“\nThe Duck says...”);
        testDuck(duck);
        
        System.out.println(“\nThe TurkeyAdapter says...”);
        testDuck(turkeyAdapter);
        }
        static void testDuck(Duck duck) {
            duck.quack();
            duck.fly();
    }
}

기존: 오리 클래스
새로운: 칠면조 클래스
사용자가 보기에 칠면조도 오리처럼 다룰 수 있도록 하기 위함이 목적.
-> 기존을 수정하지 않아도 됨.

 

 

The Adapter Pattern

: 한 클래스의 인터페이스를 클라이언트에서 사용하고자 하는 다른 인터페이스로 변환한다.

인터페이스 호환성 문제 때문에 같이 쓸 수 없던 클래스들을 연결해서 쓸 수 있다.

클라이언트는 바꿀 필요가 없다.

 

두가지 종류가 있다.

1. Object Adapter

2. Class Adapter

이건 다중 상속이 필요하다. 자바는 다중 상속이 불가능하므로 사용할 수 없다. 

Adapter를 Target과 Adaptee 모두의 서브 클래스로 만들어서 사용한다.

 

 

 

실제사용 예

enumerator로 쓰여진 옛 코드를 새 코드 iterator로 쓰고 싶을 때 adapter가 필요하다

public class EnumerationIterator implements Iterator
{
    Enumeration enum;
    public EnumerationIterator(Enumeration enum) {
    	this.enum = enum;
    }
    public boolean hasNext() {
    	return enum.hasMoreElements();
    }
    public Object next() {
    	return enum.nextElement();
    }
    public void remove() {
    	throw new UnsupportedOperationException(); 
        //enum에는 Iterator의 remove 메소드 기능이 없어서 예외처리. 아무것도 안하면 됨
    }
}

 

 

The Facade Pattern

: subsystem의 인터페이스들을 단일화된 인터페이스 하나로 제공한다.

subsystem을 쉽게 사용할 수 있도록 하기 위해 사용하는 설계방식

 

집에서 영화를 본다고 가정해보자.

팝콘을 튀기고 조명을 줄이고 스크린을 내리고 프로젝터를 키고...

할 일이 많다. 

이걸 일일히 조정하려면 굉장히 피곤할 것이다.

Facade Pattern으로 만들어보자

 

HomeTheaterFacade 클래스가 모든걸 해결해준다.

 

 

 

코드

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,
        PopcornPopper popper) {
        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(“Get ready to watch a movie...”);
        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(“Shutting movie theater down...”);
        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) {
        // instantiate components here
        
        HomeTheaterFacade homeTheater =
            new HomeTheaterFacade(amp, tuner, dvd, cd, projector, screen, lights, popper);
        
        homeTheater.watchMovie(“Raiders of the Lost Ark”);
        homeTheater.endMovie();
	}
}

 

 

The Principle of Least Knowledge

: 직접적으로 관련있는 애랑만 대화(호출)하겠다.
-> 관련있는 애?

1. 자기 자신
2. 파라미터로 넘어온 객체
3. 자신이 메소드 상에서 local로 만든 객체
4. has-a 관계를 가지는 객체

 

잘못된 예)

public float getTemp() { //객체를 직접 가져와서 자신이 호출
    Thermometer thermometer = station.getThermometer();
    return thermometer.getTemperature();
}

올바른 예)

public float getTemp() {
	return station.getTemperature(); //객체에게 요청
}
public class Car {
    Engine engine; 
    // other instance variables
    public Car() {
        // initialize engine, etc.
    }
    public void start(Key key) {
        Doors doors = new Doors(); 
        boolean authorized = key.turns(); // 매개변수로 전달된 객체의 메소드 호출 가능
        if (authorized) {
            engine.start(); // 자신이 가지고 있는 객체이므로 메소드 호출 가능
            updateDashboardDisplay(); // 자신이 가지고 있는 메소드이므로 호출 가능
            doors.lock(); // 자신이 메소드상에서 만든 객체이므로 메소드 호출 가능
    	}
    }
    public void updateDashboardDisplay() {
    // update display
	}
}
728x90

'디자인패턴' 카테고리의 다른 글

The iterator pattern  (0) 2023.10.22
The Template Method Pattern  (0) 2023.10.22
The Command Pattern  (1) 2023.10.21
The Singleton Pattern  (1) 2023.10.21
Decorator Pattern  (2) 2023.10.21