Updated:

1. 개요

어떤 객체의 상태가 변할 때 그 객체에 의존성을 가진 객체들에게 통지해주는 패턴

감시자 패턴(Observer Pattern)은 행동 패턴(Behavioral Pattern)의 한 종류로, 어떤 객체의 상태가 변할 때 그 객체에 의존성을 가진 다른 객체들이 그 변화를 통지받고 자동으로 갱신될 수 있게 하는 패턴이다.

2. 행동 패턴(Behavioral Pattern)

2-1. 행동 패턴이란?

행동 패턴이란 처리의 책임을 어떤 객체에게 할당하는 것이 좋은지, 알고리즘을 어떤 객체에 정의하는 것이 좋은지 등의 책임 분배와 관련된 패턴이다.

2-2. 행동 패턴 종류

3. 구성

[출처 : GoF의 디자인 패턴]

  • Subject : 감시자 객체를 추가하거나 빼는 기능을 정의한 인터페이스

  • Observer : Subject의 변화에 따른 갱신에 필요한 기능을 정의한 인터페이스

  • ConcreteSubject : Subject 인터페이스 구현체

  • ConcreteObserver : Observer 인터페이스 구현체

4. 예제 코드

엑셀에서 같은 데이터에 대해 막대 그래프, 원형 그래프, 꺾은선 그래프로 표현되어 있는 경우, 데이터가 바뀌면 세 그래프 모두 갱신되어야 한다. Observer Pattern을 이용하여 데이터가 갱신되었을 때 그래프의 값을 모두 갱신시키는 과정을 코드로 구현해보자.

4-1. Subject

[Subject.java]

1
2
3
4
5
6
7
public interface Subject {

    int getState();
    void setState(int state);
    void attach(Observer observer);
    void notifyAllObservers();
}

4-2. ConcreteSubject

[ConcreteSubject.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
public class ConcreteSubject implements Subject {

    private List<Observer> observers = new ArrayList<>();
    private int state;

    @Override
    public int getState() {
        return state;
    }

    @Override
    public void setState(int state) {
        this.state = state;
        notifyAllObservers();
    }

    @Override
    public void attach(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void notifyAllObservers() {
        for(Observer observer : observers) {
            observer.update();
        }
    }
}

4-3. Observer

[Observer.java]

1
2
3
4
public interface Observer {

    void update();
}

4-4. ConcreteObserver

[BarGraphObserver.java]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class BarGraphObserver implements Observer {

    private Subject subject;

    public BarGraphObserver(Subject subject) {
        this.subject = subject;
        this.subject.attach(this);
    }

    @Override
    public void update() {
        System.out.println("Bar Graph State : " + subject.getState());
    }
}

[PieGraphObserver.java]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class PieGraphObserver implements Observer {

    private Subject subject;

    public PieGraphObserver(Subject subject) {
        this.subject = subject;
        this.subject.attach(this);
    }

    @Override
    public void update() {
        System.out.println("Pie Graph State : " + subject.getState());
    }
}

[LineGraphObserver.java]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class LineGraphObserver implements Observer {

    private Subject subject;

    public LineGraphObserver(Subject subject) {
        this.subject = subject;
        this.subject.attach(this);
    }

    @Override
    public void update() {
        System.out.println("Line Graph State : " + subject.getState());
    }
}

5. 테스트

[Clinet.java]

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Client {

    public static void main(String[] args) {
        Subject subject = new ConcreteSubject();
        new BarGraphObserver(subject);
        new PieGraphObserver(subject);
        new LineGraphObserver(subject);

        subject.setState(10);
        System.out.println("-----------------------");
        subject.setState(15);
    }
}

[실행 결과]

6. 특징

  • 낮은 결합도 : 인터페이스에 의존하므로 낮은 결합도를 가짐

  • 실시간 전파 : 한 객체의 변경사항을 실시간으로 다른 객체에 전파 가능

  • 예측하지 못한 갱신 : 무엇이 변했는지 따로 관리하지 않으면, 변경의 유추가 어려움

Updated:

Leave a comment