Java/Java 자료실

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

Chipmunks 2018. 10. 23.
728x90


어댑터 패턴 (Adapter Pattern)

한 클래스의 인터페이스를 클라이언트에서 사용하고자 하는 다른 인터페이스로 변환합니다. 어댑터를 이용하면 인터페이스 호환성 문제 때문에 같이 쓸 수 없는 클래스들을 연결해서 쓸 수 있습니다.

다이어그램




퍼사드 패턴 (Facade Pattern)

어떤 서브시스템의 일련의 인터페이스에 대한 통합된 인터페이스를 제공합니다. 퍼사드에서 고수준 인터페이스를 정의하기 때문에 서브시스템을 더 쉽게 사용할 수 있습니다.

퍼사드 예제 다이어그램




객체지향 원칙

데메테르의 법칙(Law of Demeter) = 최소 지식 원칙

객체 사이의 상호작용은 될 수 있으면 아주 가까운 객체와 하는 것이 좋습니다.
즉, 시스템을 디자인할 때, 어떤 객체든 상호작용하는 클래스의 개수에 주의해야 합니다. 또한 어떤 식으로 상호작용을 하는지에도 주의해야 합니다.

여러 클래스들이 복잡하게 얽혀, 시스템을 약간 수정했을 때 스파게티처럼 줄줄이 고쳐야 하는 상황을 방지할 수 있습니다. 서로 복잡하게 의존하고 있으면 관리하기 힘들고, 남이 보기에도 이해하기가 어렵습니다.

다른 객체와 "잘" 상호작용 하기

 여러 객체와 얽히지 않으면서 잘 상호작용하는 방법은 다음과 같습니다. 다음 네 종류의 객체의 메소드만을 호출하면 복잡하게 얽히지 않을 수 있습니다. 객체 O의 메소드 M에서는 다음과 같은 메소드를 호출해야 합니다.

  1. O 객체 자체
  2. M 메소드에 매개변수로 전달된 객체
  3. M 메소드에서 생성하거나 인스턴스로 만든 객체
  4. O 객체에 속하는 구성요소

1
2
3
4
public float getTemp() {
    Thermometer thermometer = station.getThermometer();
    return thermometer.getTemperature();
}
cs

station 객체 안에 있는 getThermometer() 함수로 직접, Thermometer 객체를 가져옵니다. 그러나, 이 객체는 다리 하나를 건너면서까지 알 필요가 없습니다. 단지 station 객체가 대신 요청을 해주면 됩니다.

1
2
3
public float getTemp() {
    return station.getTemperature();
}
cs

Station 클래스에 thermometer에 요청을 해 주는 새 메소드를 추가했습니다. 이제, 본 객체는 Thermometer 클래스를 알 필요가 없어졌습니다!

예제 코드

1. 어댑터 패턴 : 오리 예제 수정하기

- ducks/Duck.java

1
2
3
4
5
6
7
package ducks;
 
public interface Duck {
    public void quack();
    public void fly();
}
 
cs


- ducks/MallardDuck.java


1
2
3
4
5
6
7
8
9
10
11
12
package ducks;
 
public class MallardDuck implements Duck {
    public void quack() {
        System.out.println("Quack");
    }
 
    public void fly() {
        System.out.println("I'm flying");
    }
}
 
cs


- ducks/Turkey.java


1
2
3
4
5
6
7
package ducks;
 
public interface Turkey {
    public void gobble();
    public void fly();
}
 
cs


- ducks/WildTurkey.java


1
2
3
4
5
6
7
8
9
10
11
12
package ducks;
 
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");
    }
}
 
cs


- ducks/TurkeyAdapter.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package ducks;
 
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();
        }
    }
}
 
cs


- ducks/DuckTestDrive.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package ducks;
 
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();
    }
}
 
cs


- ducks/DuckAdapter.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package ducks;
import java.util.Random;
 
public class DuckAdapter implements Turkey {
    Duck duck;
    Random rand;
 
    public DuckAdapter(Duck duck) {
        this.duck = duck;
        rand = new Random();
    }
    
    public void gobble() {
        duck.quack();
    }
  
    public void fly() {
        if (rand.nextInt(5)  == 0) {
             duck.fly();
        }
    }
}
 
cs


- ducks/TurkeyTestDrive.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package ducks;
 
public class TurkeyTestDrive {
    public static void main(String[] args) {
        MallardDuck duck = new MallardDuck();
        Turkey duckAdapter = new DuckAdapter(duck);
 
        for(int i=0;i<10;i++) {
            System.out.println("The DuckAdapter says...");
            duckAdapter.gobble();
            duckAdapter.fly();
        }
    }
}
 
cs


2. 어댑터 패턴 :  자바 구 Enumeration 인터페이스를 신 Iterator 클래스와 호환시키기

- iterenum/EnumerationIterator.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package iterenum;
 
import java.util.*;
 
public class EnumerationIterator implements Iterator<Object> {
    Enumeration<?> enumeration;
 
    public EnumerationIterator(Enumeration<?> enumeration) {
        this.enumeration = enumeration;
    }
 
    public boolean hasNext() {
        return enumeration.hasMoreElements();
    }
 
    public Object next() {
        return enumeration.nextElement();
    }
 
    public void remove() {
        throw new UnsupportedOperationException();
    }
}
 
cs


- iterenum/EnumerationIteratorTestDrive.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
package iterenum;
 
import java.util.*;
 
public class EnumerationIteratorTestDrive {
    public static void main (String args[]) {
        Vector<String> v = new Vector<String>(Arrays.asList(args));
        Iterator<?> iterator = new EnumerationIterator(v.elements());
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}
 
cs


- iterenum/IteratorEnumeration.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package iterenum;
 
import java.util.*;
 
public class IteratorEnumeration implements Enumeration<Object> {
    Iterator<?> iterator;
 
    public IteratorEnumeration(Iterator<?> iterator) {
        this.iterator = iterator;
    }
 
    public boolean hasMoreElements() {
        return iterator.hasNext();
    }
 
    public Object nextElement() {
        return iterator.next();
    }
}
 
cs


- iterenum/IteratorEnumeration.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
package iterenum;
 
import java.util.*;
 
public class IteratorEnumerationTestDrive {
    public static void main (String args[]) {
        ArrayList<String> l = new ArrayList<String>(Arrays.asList(args));
        Enumeration<?> enumeration = new IteratorEnumeration(l.iterator());
        while (enumeration.hasMoreElements()) {
            System.out.println(enumeration.nextElement());
        }
    }
}
 
cs


3. 퍼사드 패턴

- hometheater/Amplifier.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package hometheater;
 
public class Amplifier {
    String description;
    Tuner tuner;
    DvdPlayer dvd;
    CdPlayer cd;
    
    public Amplifier(String description) {
        this.description = description;
    }
 
    public void on() {
        System.out.println(description + " on");
    }
 
    public void off() {
        System.out.println(description + " off");
    }
 
    public void setStereoSound() {
        System.out.println(description + " stereo mode on");
    }
 
    public void setSurroundSound() {
        System.out.println(description + " surround sound on (5 speakers, 1 subwoofer)");
    }
 
    public void setVolume(int level) {
        System.out.println(description + " setting volume to " + level);
    }
 
    public void setTuner(Tuner tuner) {
        System.out.println(description + " setting tuner to " + dvd);
        this.tuner = tuner;
    }
  
    public void setDvd(DvdPlayer dvd) {
        System.out.println(description + " setting DVD player to " + dvd);
        this.dvd = dvd;
    }
 
    public void setCd(CdPlayer cd) {
        System.out.println(description + " setting CD player to " + cd);
        this.cd = cd;
    }
 
    public String toString() {
        return description;
    }
}
 
cs


- hometheater/Tuner.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package hometheater;
 
public class Tuner {
    String description;
    Amplifier amplifier;
    double frequency;
 
    public Tuner(String description, Amplifier amplifier) {
        this.description = description;
    }
 
    public void on() {
        System.out.println(description + " on");
    }
 
    public void off() {
        System.out.println(description + " off");
    }
 
    public void setFrequency(double frequency) {
        System.out.println(description + " setting frequency to " + frequency);
        this.frequency = frequency;
    }
 
    public void setAm() {
        System.out.println(description + " setting AM mode");
    }
 
    public void setFm() {
        System.out.println(description + " setting FM mode");
    }
 
    public String toString() {
        return description;
    }
}
 
cs


- hometheater/DvdPlayer.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package hometheater;
 
public class DvdPlayer {
    String description;
    int currentTrack;
    Amplifier amplifier;
    String movie;
    
    public DvdPlayer(String description, Amplifier amplifier) {
        this.description = description;
        this.amplifier = amplifier;
    }
 
    public void on() {
        System.out.println(description + " on");
    }
 
    public void off() {
        System.out.println(description + " off");
    }
 
        public void eject() {
        movie = null;
                System.out.println(description + " eject");
        }
 
    public void play(String movie) {
        this.movie = movie;
        currentTrack = 0;
        System.out.println(description + " playing \"" + movie + "\"");
    }
 
    public void play(int track) {
        if (movie == null) {
            System.out.println(description + " can't play track " + track + " no dvd inserted");
        } else {
            currentTrack = track;
            System.out.println(description + " playing track " + currentTrack + " of \"" + movie + "\"");
        }
    }
 
    public void stop() {
        currentTrack = 0;
        System.out.println(description + " stopped \"" + movie + "\"");
    }
 
    public void pause() {
        System.out.println(description + " paused \"" + movie + "\"");
    }
 
    public void setTwoChannelAudio() {
        System.out.println(description + " set two channel audio");
    }
 
    public void setSurroundAudio() {
        System.out.println(description + " set surround audio");
    }
 
    public String toString() {
        return description;
    }
}
 
cs


- hometheater/CdPlayer.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package hometheater;
 
public class CdPlayer {
    String description;
    int currentTrack;
    Amplifier amplifier;
    String title;
    
    public CdPlayer(String description, Amplifier amplifier) {
        this.description = description;
        this.amplifier = amplifier;
    }
 
    public void on() {
        System.out.println(description + " on");
    }
 
    public void off() {
        System.out.println(description + " off");
    }
 
    public void eject() {
        title = null;
        System.out.println(description + " eject");
    }
 
    public void play(String title) {
        this.title = title;
        currentTrack = 0;
        System.out.println(description + " playing \"" + title + "\"");
    }
 
    public void play(int track) {
        if (title == null) {
            System.out.println(description + " can't play track " + currentTrack + 
                    ", no cd inserted");
        } else {
            currentTrack = track;
            System.out.println(description + " playing track " + currentTrack);
        }
    }
 
    public void stop() {
        currentTrack = 0;
        System.out.println(description + " stopped");
    }
 
    public void pause() {
        System.out.println(description + " paused \"" + title + "\"");
    }
 
    public String toString() {
        return description;
    }
}
 
cs


- hometheater/Projector.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package hometheater;
 
public class Projector {
    String description;
    DvdPlayer dvdPlayer;
    
    public Projector(String description, DvdPlayer dvdPlayer) {
        this.description = description;
        this.dvdPlayer = dvdPlayer;
    }
 
    public void on() {
        System.out.println(description + " on");
    }
 
    public void off() {
        System.out.println(description + " off");
    }
 
    public void wideScreenMode() {
        System.out.println(description + " in widescreen mode (16x9 aspect ratio)");
    }
 
    public void tvMode() {
        System.out.println(description + " in tv mode (4x3 aspect ratio)");
    }
  
        public String toString() {
                return description;
        }
}
 
cs


- hometheater/TheaterLights.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package hometheater;
 
public class TheaterLights {
    String description;
 
    public TheaterLights(String description) {
        this.description = description;
    }
 
    public void on() {
        System.out.println(description + " on");
    }
 
    public void off() {
        System.out.println(description + " off");
    }
 
    public void dim(int level) {
        System.out.println(description + " dimming to " + level  + "%");
    }
 
    public String toString() {
        return description;
    }
}
 
cs


- hometheater/Screen.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package hometheater;
 
public class Screen {
    String description;
 
    public Screen(String description) {
        this.description = description;
    }
 
    public void up() {
        System.out.println(description + " going up");
    }
 
    public void down() {
        System.out.println(description + " going down");
    }
 
 
    public String toString() {
        return description;
    }
}
 
cs


- hometheater/PopcornPopper.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package hometheater;
 
public class PopcornPopper {
    String description;
    
    public PopcornPopper(String description) {
        this.description = description;
    }
 
    public void on() {
        System.out.println(description + " on");
    }
 
    public void off() {
        System.out.println(description + " off");
    }
 
    public void pop() {
        System.out.println(description + " popping popcorn!");
    }
 
  
        public String toString() {
                return description;
        }
}
 
cs


- hometheater/HomeTheaterFacade.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package hometheater;
 
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 void listenToCd(String cdTitle) {
        System.out.println("Get ready for an audiopile experence...");
        lights.on();
        amp.on();
        amp.setVolume(5);
        amp.setCd(cd);
        amp.setStereoSound();
        cd.on();
        cd.play(cdTitle);
    }
 
    public void endCd() {
        System.out.println("Shutting down CD...");
        amp.off();
        amp.setCd(cd);
        cd.eject();
        cd.off();
    }
 
    public void listenToRadio(double frequency) {
        System.out.println("Tuning in the airwaves...");
        tuner.on();
        tuner.setFrequency(frequency);
        amp.on();
        amp.setVolume(5);
        amp.setTuner(tuner);
    }
 
    public void endRadio() {
        System.out.println("Shutting down the tuner...");
        tuner.off();
        amp.off();
    }
}
 
cs


- hometheater/HomeTheaterTestDrive.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package hometheater;
 
public class HomeTheaterTestDrive {
    public static void main(String[] args) {
        Amplifier amp = new Amplifier("Top-O-Line Amplifier");
        Tuner tuner = new Tuner("Top-O-Line AM/FM Tuner", amp);
        DvdPlayer dvd = new DvdPlayer("Top-O-Line DVD Player", amp);
        CdPlayer cd = new CdPlayer("Top-O-Line CD Player", amp);
        Projector projector = new Projector("Top-O-Line Projector", dvd);
        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, dvd, cd, 
                        projector, screen, lights, popper);
 
        homeTheater.watchMovie("Raiders of the Lost Ark");
        homeTheater.endMovie();
    }
}
 
cs


댓글