[Design Pattern] GoF 행위 패턴 - 옵서버 패턴(Observer Pattern)



옵서버 패턴(Observer Pattern)

GoF 디자인 패턴 중 행위 패턴에 해당한다.
객체의 상태 변화를 관찰하여 변화가 발생하면 변화를 통지받고 자동으로 갱신될 수 있게 한다. 주로 분산 이벤트 핸들링 시스템을 만들 때 사용한다.


사용법

  • 어떤 객체의 변화로 인해 다른 객체가 변경되어야 하는데, 프로그래머들은 얼마나 많은 객체들이 변경되어야 하는지 몰라도 될 때
  • 외부에서 발생한 이벤트에 대해 결과를 처리해야 할 때


구조

img

  • 데이터의 변화가 발생할 Subject는 Observer들을 알고 있다.
  • Subject는 변화가 발생하면 Observer에게 notify한다.


장점

  • Subject와 Observer 클래스 사이에는 추상적인 결합도만 존재함
  • 브로드캐스트 방식의 교류 가능 : Subject는 변화 발생 시 구체적인 수신자를 지정할 필요가 없다. 상태가 변화했다는 사실만 전달하면 변화를 처리할지 말지는 Observer가 결정한다.


예제

클래스 다이어그램

img


구현

Observable에 Observer를 등록한다. Observable에 변화가 생기면 프로그래머가 직접 상태를 업데이트해주는 것이 아니라, Observable이 직접 등록된 Observer들에게 변화를 알린다.(notify)
Observer는 알림을 받으면 그에 따른 작업을 수행한다.

import subject.IntegerObservable;
import observer.concrete.CircleObserver;
import observer.concrete.StarObserver;

public class Main {
    public static void main(String[] args) {
        IntegerObservable observable = new IntegerObservable();
        StarObserver starObserver = new StarObserver();
        CircleObserver circleObserver = new CircleObserver();

        observable.registerObserver(starObserver);
        observable.registerObserver(circleObserver);

        System.out.println("\n>> Data Changed");
        observable.setData(2);

        System.out.println("\n>> Data Changed");
        observable.setData(5);

        observable.unregisterObserver(starObserver);
        observable.unregisterObserver(circleObserver);

        System.out.println("\n>> Data Changed");
        observable.setData(10);
    }
}

[실행 결과]
>> Data Changed
<< Star Draw : **
<< Circle Draw : oo

>> Data Changed
<< Star Draw : *****
<< Circle Draw : ooooo

>> Data Changed


소스 코드

전체 소스 코드

package subject;

import observer.Observer;

import java.util.ArrayList;

public class Observable {

    private ArrayList<Observer> observerCollection = new ArrayList<>();

    public void registerObserver(Observer observer) {
        observerCollection.add(observer);
    }

    public void unregisterObserver(Observer observer) {
        observerCollection.remove(observer);
    }

    void notifyObservers() {
        for(Observer observer : observerCollection) {
            observer.update(this);
        }
    }
}

package subject;

public class IntegerObservable extends Observable{

    private int data;

    public int getData() {
        return data;
    }

    public void setData(int data) {
        this.data = data;
        notifyObservers();
    }
}

package observer.concrete;

import observer.Observer;
import subject.IntegerObservable;
import subject.Observable;

public class StarObserver implements Observer {
    @Override
    public void update(Observable observable) {
        System.out.print("<< Star Draw : ");
        for (int i = 0; i < ((IntegerObservable) observable).getData(); i++) {
            System.out.print("*");
        }
        System.out.println();
    }
}

package observer.concrete;

import observer.Observer;
import subject.IntegerObservable;
import subject.Observable;

public class CircleObserver implements Observer {
    @Override
    public void update(Observable observable) {
        System.out.print("<< Circle Draw : ");
        for (int i = 0; i < ((IntegerObservable) observable).getData(); i++) {
            System.out.print("o");
        }
        System.out.println();
    }
}



:bookmark: REFERENCE
에릭 감마 외 3명, 「GoF의 디자인 패턴」, 피어슨에듀케이션코리아
옵저버 패턴