개발자로서 살아남기

면접을 위한 CS 전공지식 노트 - 1.1.4 옵저버 패턴

코드 살인마 2022. 10. 22. 00:34
728x90

옵져버 패턴

옵저버 패턴(observer pattern)은 주체가 어떤 객체(subject)의 상태 변화를 관찰하다가 상태 변화가 있을 때마다 메서드 등을 통해 옵저버 목록에 있는 옵저버들에게 변화를 알려주는 디자인 패턴이다.

Untitled

대표적인 사례

  • 트위터

Untitled 1

  • 유튜브

Untitled 2

특정 정보를 여러 뷰에서 동시에 얻기 위해 주제자(Subject)구독자(Observer)등록(Register)
하여 정보를 받는(갱신, Notify) 것을 옵저버 패턴(Observer pattern)이라 한다. 물론 등록을 했으니 해지(Remove)도 가능하다.

코드로 보는 옵져버 패턴

그럼 이제 본격적으로 코드를 확인해 보겠습니다. 여기서 보여드릴 예시는 Subject class에서 값을 변경하면 등록된 모든 Observer들에게 갱신하는 간단한 구조이다.

Subject interface입니다. Observer를 등록, 해제, 갱신하기 위한 API를 나타낸다.

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

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

Observer interface이다.


interface Observer {
    public void update(); 
}

Topic는 Subject interface를 상속받습니다. 그리고 ArrayList를 사용하여 observer 정보를 가지고 있다.

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

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

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

    @Override
    public void unregister(Observer obj) {
        observers.remove(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();
    }
}

아래는 각 Observer interface를 상속받는 TopicSubscriber class이다.

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); 
    } 
}

이제 메인 프로그램 입니다. 3개의 Observer 인스턴스를 생성하고, topic 인스턴스에 등록한다.

이후 postMessage메서드를 호출한다.

public class HelloWorld { 
    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("amumu is op champion!!"); 
    }
}
/*
Message sended to Topic: amumu is op champion!!
a:: got message >> amumu is op champion!!
b:: got message >> amumu is op champion!!
c:: got message >> amumu is op champion!!
*/

 

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

 

Untitled 3

 

예를 들어 주체라고 볼 수 있는 모델(model)에서 변경 사항이 생겨 update() 메서드로 옵저버인 뷰에 알려주고 이를 기반으로 컨트롤러(controller) 등이 작동한다.

 

이후 MVC 패턴에 대해 알아본다.