디자인패턴중 옵저버패턴에 대해 설명을 드리려고 글을 작성합니다.
설명
옵저버패턴은 옵저버블에 옵저버를 등록하여 옵저버블에 상태 변화가 있을 때마다 메서드등을 통해 옵저버에게 통지하는 디자인패턴입니다.
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에 대해 설명을 드리겠습니다.
부족하거나 잘못된 점은 댓글로 작성해주시면 감사하겠습니다.!!