1.可以解耦所有源文件之间的交互编译依赖,作为中间者控制交互
2.可使用不同枚举作为软件的模块消息或是数据标识,且编译无需依赖枚举头文件,可随意修改
3.简单,只需少量代码即可实现,支持注册和触发
4.消息总线支持优先级,控制消息触发顺序
#pragma once
#include
#include
#include
#include
class MsgHandler {
public:
static MsgHandler* GetInstance() {
static MsgHandler i;
return &i;
}
void RegisterMsgHandler_(const char* msg, std::function<void()> func, int priority = 0) {
globalMsgHandlers_[msg].insert({ priority,[=](std::any info) {func(); } });
}
void RegisterMsgHandler_(const char* msg, std::function<void(std::any info)> func, int priority = 0) {
globalMsgHandlers_[msg].insert({ priority, func });
}
void TriggerMsg_(const char* msg, std::any info) {
if (bool findHanlder = globalMsgHandlers_.find(msg) != globalMsgHandlers_.end()) {
for (auto& pair : globalMsgHandlers_[msg]) {
pair.second(info);
}
}
}
private:
MsgHandler() = default;
std::unordered_map<const char*, std::multimap<int, std::function<void(std::any)>>> globalMsgHandlers_;
};
#define GMsgHandler MsgHandler::GetInstance()
#define RegisterMsgHandler(msg, ...) GMsgHandler->RegisterMsgHandler_(#msg, __VA_ARGS__)
#define TriggerMsg(msg, ...) GMsgHandler->TriggerMsg_(#msg, __VA_ARGS__)
例如仅使用到某个类中的一个数据成员,但是又不想包含该类的头文件并调用Get函数
#pragma once
#include
#include
#include
#include
class IdentityData {
public:
static IdentityData* GetInstance() {
static IdentityData i;
return &i;
}
void RegisterIdentityData_(const char* msg, std::any data) {
globalIdentityData_.insert({ msg, std::move(data) });
}
template<typename T>
T GetRegisterData_(const char* msg) {
if (bool findData = globalIdentityData_.find(msg) != globalIdentityData_.end()) {
return std::any_cast<std::reference_wrapper<T>>(globalIdentityData_[msg]);
}
return T{};
}
private:
IdentityData() = default;
std::unordered_map<const char*, std::any> globalIdentityData_;
};
#define GIdentityData IdentityData::GetInstance()
#define RegisterIdentityData(msg, data) GIdentityData->RegisterIdentityData_(#msg, std::ref(data))
#define GetRegisterData(msg, ...) GIdentityData->GetRegisterData_<__VA_ARGS__>(#msg)
#include
#include "MsgHandler.h"
#include "IdentityData.h"
enum class ESoftModelAMsg {
NEW,
DEL,
};
enum class ESoftModelBMsg {
UPDATE,
};
enum class EData {
AAA,
};
struct TestClass {
TestClass() {
RegisterMsgHandler(ESoftModelAMsg::NEW, [this] {
std::cout << "class func called" << a << std::endl;
}, 0);
RegisterMsgHandler(ESoftModelAMsg::NEW, [this](const std::any& info) {
a = std::any_cast<int>(info);
std::cout << "class para func called" << a << std::endl;
}, 1);
}
private:
int a = 5;
};
int main()
{
TestClass t;
RegisterMsgHandler(ESoftModelAMsg::NEW, [] {
std::cout << "normal func called" << std::endl;
}, 2);
RegisterMsgHandler(ESoftModelAMsg::NEW, [] (const std::any& info){
int para = std::any_cast<int>(info);
std::cout << "normal para func called" << para << std::endl;
}, 3);
TriggerMsg(ESoftModelAMsg::NEW, 5);
int dataA = 5;
RegisterIdentityData(EData::AAA, dataA);
std::cout << "dataA = " << GetRegisterData(EData::AAA, int) << std::endl;
dataA = 6;
std::cout << "dataA = " << GetRegisterData(EData::AAA, int) << std::endl;
getchar();
}