본문 바로가기

지식/Computer Science

[디자인 패턴] 옵저버 패턴 (Observer Pattern)

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

 

한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체들에게 연락이 가고, 자동으로 정보가 갱신되는 1:N 관계(혹은 1대1)를 정의합니다.

 

여기서 주체란 객체의 상태 변화를 보고 있는 관찰자

옵저버들이란 이 객체의 상태 변화에 따라 전달되는 메서드 등을 기반으로 추가 변화 사항이 생기는 객체들

 

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

내가 어떤 사람인 주체를 팔로우했다면 주체가 포스팅을 올리면 알림이 팔로워에게 가는 구조입니다.

 

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

Model에서 변경 사항이 생겨 update()메서드로 옵저버인 View에게 알려주고 이를 기반으로 Controller등이 작동합니다.

 

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

interface Observer{ // 옵저버의 인터페이스
    public void update();
}

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

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 main{
    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("publisher post message"); // 주체에 메세지 전송
    }
}

topic은 주체이자 객체가 됩니다.

Observer a = new TopicSubscriber("a", topic); 으로 옵저버를 선언할 때 해당 이름과 어떠한 토픽의 옵저버가 될 것인지를 정합니다.