본문 바로가기
💻 programming/design pattern

[c++] Observer Pattern

by 연구원-A 2020. 12. 16.
반응형

ko.wikipedia.org/wiki/%EC%98%B5%EC%84%9C%EB%B2%84_%ED%8C%A8%ED%84%B4

 

옵서버 패턴 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 옵서버 패턴(observer pattern)은 객체의 상태 변화를 관찰하는 관찰자들, 즉 옵저버들의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 등을 통해 객체

ko.wikipedia.org

옵저버 패턴(observer pattern)은 객체의 상태 변화를 관찰하는 관찰자들, 즉 옵저버들의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하도록 하는 디자인 패턴입니다. 주로 분산 이벤트 핸들링 시스템을 구현하는 데 사용되며, 발행/구독 (publish/subscribe) 모델로 알려져 있습니다.

 

  • Subject: 관찰 대상에 해당하며, 이벤트를 발생시키는 주체입니다
    • Subject는 Observer를 가지고 있으면서 객체에 이벤트가 발생되면 Observer의 notify()함수를 호출합니다
  • Observer: 관찰 대상에 등록되는 옵저버 (리스너)에 해당하며, 옵저버들은 관찰 대상인 객체가 발생시키는 이벤트를 받아 처리합니다.

 

main function

#include <iostream>
#include <vector>
#include <memory>

#include "EventManager.h"
#include "event/GudsHandler.h"
#include "event/RoutineHandler.h"

using namespace std;

int main() {
    std::unique_ptr<EventManager> event_manager_ = std::make_unique<EventManager>();
    GudsHandler a;
    RoutineHandler b1(1), b2(2);

    // add subscriber
    event_manager_->AddEventHandler(EventType::guds, &a);
    event_manager_->AddEventHandler(EventType::routine, &b1);
    event_manager_->AddEventHandler(EventType::routine, &b2);

    // broadcast data to subscribers
    event_manager_->Notify(EventType::guds, 10);
    event_manager_->Notify(EventType::routine, 20);
}

 

EventManager (Subject)

#ifndef __EVENT_MANAGER_H_
#define __EVENT_MANAGER_H_

#include <iostream>
#include <vector>
#include <memory>
#include <set>
#include <map>

#include "event/IEventHandler.h"

using namespace std;

enum class EventType : unsigned int { guds = 1, routine = 2 };

class EventManager {
private:
    std::map<EventType, std::set<IEventHandler*>> event_handlers;
public:
    void AddEventHandler(EventType type, IEventHandler* handler);
    void DelEventHandler(EventType type, IEventHandler* handler);
    void Notify(EventType type, int data);
};

void EventManager::AddEventHandler(EventType type, IEventHandler* handler) {
    if(event_handlers.find(type) == event_handlers.end()) {
        event_handlers.insert({type, {handler}});
        return;
    }
    auto typed_handlers = event_handlers.find(type);
    if(typed_handlers->second.find(handler) == typed_handlers->second.end()) {
        typed_handlers->second.insert(handler);
        event_handlers.insert({type, typed_handlers->second});
    }
}

void EventManager::DelEventHandler(EventType type, IEventHandler* handler) {
    if(event_handlers.find(type) == event_handlers.end()) {
        return;
    }
    auto typed_handlers = event_handlers.find(type);
    if(typed_handlers->second.find(handler) != typed_handlers->second.end()) {
        typed_handlers->second.erase(handler);
        event_handlers[type] = typed_handlers->second;
    }
}

void EventManager::Notify(EventType type, int data) {
    if(event_handlers.find(type) == event_handlers.end()) {
        return;
    }
    auto typed_handlers = event_handlers.find(type);

    for(auto p : typed_handlers->second) {
        if(p != nullptr) {
            p->execute(data);
        }
    }
}
#endif

 

IEventHandler (Observer)

#ifndef __IEVENT_HANDLER_H_
#define __IEVENT_HANDLER_H_
#include <iostream>
#include <vector>
#include <memory>

using namespace std;

class IEventHandler {
public:
    virtual void execute(int data) = 0;
};
#endif

 

RoutineHandler (ConcreteObserver1)

#ifndef __ROUTINE_HANDLER_H_
#define __ROUTINE_HANDLER_H_
#include <iostream>
#include <vector>
#include <memory>

#include "event/IEventHandler.h"

using namespace std;

class RoutineHandler : public IEventHandler {
public:
    RoutineHandler(int rid) : rid_(rid) {}
    void execute(int data) {
        print();
        cout << __func__ << " " << data << endl;
    }
private:
    inline void print() { cout << "rid: " << rid_ << endl; }
    int rid_;
};
#endif

 

주의사항

옵서버 패턴이 많이 쓰인 시스템에서는 순환 실행을 막는 메커니즘이 필요합니다.

이벤트 X가 발생하면 옵저버A가 옵저버B를 갱신한다고 가정해봅시다. 그런데 옵저버B가 이 처리를 위해 옵저버A를 갱신한다면, 이는 다시 A로 하여금 이벤트 X를 발생하게 합니다. 이같은 상황을 막기 위해 이벤트 X가 한번 처리된 후에는 A가 이벤트 X를 다시 발생시키지 않는 방법이 요구되고 있습니다.

반응형

'💻 programming > design pattern' 카테고리의 다른 글

[c++] Mediator Pattern  (0) 2020.12.16
[c++] Visitor Pattern  (0) 2020.12.16

댓글