티스토리 뷰

옵저버 패턴(Observer Pattern)이란?

주체가 어떤 객체(subject)의 상태 변화를 관찰하다가 상태 변화가 있을 때 마다 옵저버들에게 변화를 알려주는 패턴이다.

즉 주체란 객체의 상태 변화를 관찰하는 관찰자이며, 옵저버들이란 이 객체의 상태 변화에 따라 메시지를 전달 받는 객체를 의미한다.

또한 객체와 주체가 합쳐져 객체의 상태가 변할 때 마다 스스로 옵저버들에게 메시지를 전달할 수도 있다.

 

옵저버 패턴을 활용한 서비스로 트위터가 있다.

주체를 팔로우했다면 주체가 포스팅을 할 때 마다 팔로워들에게 알림이 간다.

 

옵저버 패턴은 주로 이벤트 기반 시스템에 사용하며 MVC 패턴에도 사용된다.

예를 들어 주체(Model)에서 변경이 생기면 옵저버(View)에 알려주고 이를 기반으로 Controller가 작동한다.

 

 

옵저버 패턴의 장단점

  • 장점
    • 인터페이스를 이용한 객체 간의 결합도를 낮추어 유지 보수에 유리하다.
    • 개방 폐쇄의 원칙을 지킬 수 있다.
  • 단점
    • 옵저버에게 전달되는 순서가 보장되지 않는다.
    • 옵저버와 주체의 관계가 잘 정의되지 않으면 원치 않는 동작이 발생할 수 있다.

 

자바에서의 옵저버 패턴

import java.util.ArrayList;
import java.util.List;

interface Subject {
    void register(Observer obj);
    void notifyObservers();
    Object getUpdate(Observer obj);
}

interface Observer {
    void update();
}

class Topic implements Subject {
    private List<Observer> observers;
    private String message;

    public Topic() {
        this.observers = new ArrayList<Observer>();
        this.message = "";
    }

    @Override
    public void register(Observer obj) {
        if (!observers.contains(obj)) observers.add(obj);
    }

    @Override
    public void notifyObservers() {
        this.observers.forEach(Observer::update);
    }

    @Override
    public Object getUpdate(Observer obj) {
        return this.message;
    }

    public void postMessage(String msg) {
        System.out.println("Message sended to Topic: " + msg);
        this.message = msg;
        notifyObservers();
    }
}

class TopicSubscriber implements Observer {
    private String name;
    private Subject topic;

    public TopicSubscriber(String name, Subject topic) {
        this.name = name;
        this.topic = topic;
    }

    @Override
    public void update() {
        String msg = (String) topic.getUpdate(this);
        System.out.println(name + ": got message >> " + msg);
    }
}

public class ObserverPattern {
    public static void main(String[] args) {
        Topic topic = new Topic();
        Observer a = new TopicSubscriber("a", topic);
        Observer b = new TopicSubscriber("b", topic);
        Observer c = new TopicSubscriber("c", topic);

        topic.register(a);
        topic.register(b);
        topic.register(c);

        topic.postMessage("I like Sonny!");
    }
}

/* 출력
Message sended to Topic: I like Sonny!
a: got message >> I like Sonny!
b: got message >> I like Sonny!
c: got message >> I like Sonny!
*/

여기서 topic은 주체이자 객체가 된다.

topic에 옵저버들을 등록하고(register()), 객체의 상태가 변화되면 (postMessage()) 주체이자 객체인 topic은 옵저버들에게 메시지를 전달한다. (notifyObservers())

 

Reference