C++消息总线和数据总线,可实现代码间交互完全解耦

特性

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

你可能感兴趣的:(C++,c++,开发语言,架构,设计模式)