디자인패턴중 옵저버패턴에 대해 설명을 드리려고 글을 작성합니다.

설명

옵저버패턴은 옵저버블에 옵저버를 등록하여 옵저버블에 상태 변화가 있을 때마다 메서드등을 통해 옵저버에게 통지하는 디자인패턴입니다.

observer.png

UML 다이어그램으로 위 그림처럼 표현이 된다. Subject는 이벤트를 생성하는 객체를 표현한 것이고, register, unregister로 observer를 등록, 해제를 할 수가 있다.

notifyObserver()에서 이벤트를 생성하는데 생성할 때 마다 이벤트를 notify()라는 메소드로 넣어주면 observer는 이를 받게됩니다.

여기서 잠깐 다른 곳으로 가보자면, Observer pattern에서 이벤트(데이터)를 옵저버에게 넣어준다(PUSH) 가 되겠습니다.

하지만 반대로 자주 사용하는 iterator를 보면 데이터를 hasNext()로 있는지 확인 후에 next()로 데이터를 당겨온다(PULL).

Iterator Observer
Pull Push

이처럼 Observer와 Iterator는 상대성이 있고, 위 표로 나타낼 수 있다.

아래 코드는 옵저버 패턴을 간단하게 구현한것 옵저버블에서 2의 배수를 20까지 생성하여 옵저버에게 통지하는 코드로 IntObserverable 클래스는 Observable클래스를 상속받고 Runnable인터페이스를 implements를 받았습니다.

Observable 클래스에는 여러 메소드가 있지만 아래 2개의 메소드를 사용하였습니다.

setChanged() : 옵저버블에 변화가 있음을 알리는 메소드
notifyObserver(Object) : 변화가 어떤 것이 있는지 정보를 담을 수 있는 메소드
메인 메소드에선 Observer 객체를 생성하였는데 update라는 메소드를 오버라이드하였습니다.

update(Observable, Object) : 옵저버블에 변화를 받는 메소드
이 메소드를 통해 옵저버블에서 생성된 데이터를 통보를 받아 데이터를 조작할 수가 있다. 아래 코드에선 출력만 해줍니다.

public class Ob { 
    static class IntObservable extends Observable implements Runnable{ 
        @Override 
        public void run() { 
            for(int i = 1 ; i <= 10 ; i++) { 
                setChanged();
                notifyObservers(i); // Push 
                //int i = it.next(); // Pull 
            } 
         } 
    } 
    public static void main(String[] args) { 
        Observer ob = new Observer() {

            @Override 
            public void update(Observable arg0, Object arg1) { 
                System.out.println(Thread.currentThread().getName() + " " + arg1); 
            } 
        }; 
        IntObservable io = new IntObservable();
        io.addObserver(ob);

        ExecutorService es = Executors.newSingleThreadExecutor(); 
        es.execute(io); 
        System.out.println(Thread.currentThread().getName() + " " + "EXIT");
        es.shutdown();
    }
}

추가로 설명드리자면 여기서 Observer pattern을 보완한것이 Pub/sub이 되겠습니다.

보완점은

데이터를 제대로 받았는지 확인할 수 없다 (complete)
에러가 났을때 처리할 수가 없다(Error)
가 되겠습니다.

다음 글에서 Pub/sub에 대해 설명을 드리겠습니다.

부족하거나 잘못된 점은 댓글로 작성해주시면 감사하겠습니다.!!