消息总线模式 == 等价于 发布-订阅模式
消息总线 == 事件处理中心
观察者应该主动向消息总线注册事件,因为消息总线并不知道哪些对象需要别注册。
当主题发生变化时,主动向消息总线发送消息。
消息总线会找到关注指定消息的所有观察者,进行通告,观察者做出行动。
Observer Message Bus Subject
对上述的例子进行改写:
1.观察者应该主动向消息总线注册消息
2.消息与observer绑定,用数据结构unordered_multimap包维持
Message.h
#pragma once
enum Message {
kAdd,
kSub,
kMul,
kDiv
};
inline std::string ToMessageString(Message event) {//inline 内部链接
switch (event) {
case 0:
return "add operation";
break;
case 1:
return "sub operation";
break;
case 2:
return "mul operation";
break;
case 3:
return "div operation";
break;
}
}
subscriber.h
#pragma once
#include <string>
#include "Message.h"
class MessageBus;
class Subscriber
{
public:
Subscriber(std::string name, Message event);
void RegisterMessage(MessageBus* bus);
private:
std::string name_;
Message interested_event_;
};
subscriber.cpp
#include "subscriber.h"
#include "MessageBus.h"
#include<iostream>
Subscriber::Subscriber(std::string name, Message event)
{
name_ = name;
interested_event_ = event;
std::cout << name_ << " subscribe " << ToMessageString(interested_event_) << std::endl;
}
void Subscriber::RegisterMessage(MessageBus* bus)
{
auto func = [=]() {std::cout << name_ << " response " << ToMessageString(interested_event_) << std::endl; };
bus->AddMessage(interested_event_, func);
}
MessageBus.h
#include "subscriber.h"
#include "Message.h"
class Subscriber;
class MessageBus
{
public:
void Notify(Message event);
void AddMessage(Message event, std::function<void()> handler);//Handle Message
private:
std::unordered_multimap<Message, std::function<void()>> observers;
};
MessageBus.cpp
#include "MessageBus.h"
void MessageBus::Notify(Message event)
{
auto iterators = observers.find(event);
auto range = observers.equal_range(event);
for (auto it = range.first; it != range.second; it++) {
it->second();
}
}
void MessageBus::AddMessage(Message event, std::function<void()> handler)
{
observers.emplace(event, handler);
}
publisher.h
#pragma once
#include <string>
#include "Message.h"
class MessageBus;
class Publisher
{
public:
void Publish(MessageBus* center, Message event);
};
publisher.cpp
#include "publisher.h"
#include "MessageBus.h"
#include <iostream>
#include <string>
void Publisher::Publish(MessageBus* center, Message event)
{
std::cout << " publish : " << ToMessageString(event) << " message " << std::endl;
center->Notify(event);
}
void test_MessageBus()
{
Subscriber member_1("Alen", Message::kAdd);
Subscriber member_2("Bob", Message::kSub);
Subscriber member_3("Sam", Message::kAdd);
MessageBus bus;
//Register
member_1.RegisterMessage(&bus);
member_2.RegisterMessage(&bus);
member_3.RegisterMessage(&bus);
Publisher message_1;
message_1.Publish(&bus, Message::kSub);
message_1.Publish(&bus, Message::kDiv);
message_1.Publish(&bus, Message::kAdd);
}