IT/디자인 패턴(Design Pattern)

[디자인 패턴] 옵저버 패턴(Observer Pattern)

TevQabs 2019. 2. 15. 10:38

1) 개요

옵저버 패턴은 객체의 상태 변화를 관찰하는 관찰자 객체를 생성하여 사용하는 디자인 패턴입니다.

즉, 객체의 변화가 발생하면 그에 따르는 종속객체들이 자동으로 변화가 통지되어 그에 따른 명령을 수행하도록하는 일대다의 의존성을 정의해줍니다.


- 옵저버 패턴을 사용하는 경우
1. 분산 이벤트 핸들링 시스템 
2. 이벤트 기반 프로그래밍

- 장점
1. 객체간의 결합도가 느슨해집니다.
2. 실시간으로 효과적으로 데이터를 배분할 수 있습니다.

- 단점
1. 패턴을 잘못 구현할 경우 데이터 배분에 문제가 발생하여 위험도가 큽니다.

2) UML


3) 예제

1
2
3
4
public interface Observer {
    public void update(int runs, int wickets, float overs);
}
 
cs

1
2
3
4
5
6
public interface Subject {
    public void registerObserver(Observer o);
    public void unregisterObserver(Observer o);
    public void notifyObservers();
}
 
cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class AverageScoreDisplay implements Observer {
 
    private float runRate;
    private int predictedScore;
    
    @Override
    public void update(int runs, int wickets, float overs) {
        this.runRate = (float)runs/overs;
        this.predictedScore = (int)(this.runRate * 50);
        display();
    }
    
    public void display() {
        System.out.println("\nAverage Score Display : " +
                           "\nRun Rate : " + runRate + 
                           "\nPredictedScore : " + predictedScore);
    }
 
}
 
cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class CurrentScoreDisplay implements Observer{
    
    private int runs, wickets;
    private float overs;
    
    @Override
    public void update(int runs, int wickets, float overs) {
        this.runs = runs;
        this.wickets = wickets;
        this.overs = overs;
        display();
    }
    
    public void display() {
        System.out.println("\nCurrent Score Display : " +
                            "\nRuns: " + runs + 
                            "\nWickets:" + wickets + 
                            "\nOvers: " + overs ); 
    }
 
}
 
cs

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
public class CircketData implements Subject{
 
    int runs;
    int wickets;
    float overs;
    ArrayList<Observer> observerList;
    
    public CircketData() {
        observerList = new ArrayList<Observer>();
    }
    
    @Override
    public void registerObserver(Observer o) {
        observerList.add(o);
    }
 
    @Override
    public void unregisterObserver(Observer o) {
        observerList.remove(observerList.indexOf(o));
    }
 
    @Override
    public void notifyObservers() {
        for (Iterator<Observer> it = observerList.iterator(); it.hasNext();) {
            Observer o = it.next();
            o.update(runs, wickets, overs);
        }
    }
 
    private int getLatestRuns() {
        return 90;
    }
    
    private int getLatestWickets() {
        return 2;
    }
    
    private float getLatestOvers() {
        return (float)10.2;
    }
    
    public void dataChanged() {
        runs = getLatestRuns();
        wickets = getLatestWickets();
        overs = getLatestOvers();
        
        notifyObservers();
    }
}
cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Main {
    public static void main(String[] args) {
        AverageScoreDisplay averageScoreDisplay = 
                    new AverageScoreDisplay();
        CurrentScoreDisplay currentScoreDisplay = 
                    new CurrentScoreDisplay();
        CircketData circketData = new CircketData();
        circketData.registerObserver(averageScoreDisplay);
        circketData.registerObserver(currentScoreDisplay);
        
        circketData.dataChanged();
        
        System.out.println("\n--------- Remove AverageScoreDisplay ---------");
        circketData.unregisterObserver(averageScoreDisplay);
        circketData.dataChanged();
    }
}
 
cs