본문 바로가기
CS

[디자인패턴] 옵저버 패턴

by sangyunpark 2023. 8. 14.

옵저버 패턴

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

 

주체란?

객체의 상태 변화를 보고 있는 관찰자

 

옵저버들이란?

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

 

종류

(1) 객체와 주체가 분리되어 있는 옵저버 패턴

(2) 객체와 주체가 합쳐진 옵저버 패턴

 

예시) 트위터 옵저버 패턴

옵저버 패턴으로인해 발생하는 현상예시

사람인 주체를 '팔로우'한 경우 주체가 포스팅을 올리게 되면 알림이 '팔로워'한테 가는 현상

 

옵저버 패턴 구조

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

ex ) 주체라고 볼 수 있는 모델(Model)에서 변경 사항이 생겨 update() 메서드로 옵저버인 뷰에 알려주고 이를 기반으로 컨트롤러(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); // 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("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!

topic은 주체이자 객체가 된다.

class Topic implements Subject를 통해서 Subject interface를 구현했고,

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

'CS' 카테고리의 다른 글

[디자인 패턴] 프록시 패턴  (0) 2023.08.22
[디자인 패턴] 전략 패턴  (0) 2023.08.21
[디자인 패턴] 팩토리 패턴  (0) 2023.08.18
[디자인 패턴] 싱글톤 패턴  (0) 2023.08.18
[Database] 트랜잭션 개념  (0) 2023.08.14