C++利用模板实现消息订阅和分发功能

C++语言支持重载,模板,虚函数等特性,为编写高性能可扩展的程序提供了利器。本文就讲利用模板实现消息订阅和分发功能,感兴趣的小伙伴可以了解一下

解耦是编写程序所遵循的基本原则之一,多态是提高程序灵活性的重要方法。C++语言支持重载,模板,虚函数等特性,为编写高性能可扩展的程序提供了利器。编写大型项目时,免不了需要各个模块之间相互调用,从而产生了模块之间的耦合。不同模块之间的关系称之为耦合,耦合程度由高到底可以分为以下几类:

1. 内容耦合

内容耦合常见情形如下:

1)一个模块直接访问另一个模块的内容

2)一个模块不通过正常入口转到另一个模块

3)两个模块有部分程序代码重叠,常见在汇编语言中

4)一个模块有多个入口

2. 公共耦合

若模块都访问同一个公共数据环境,则称他们是公共耦合。

3. 外部耦合

模块通过非参数传递的方式访问同一个全局变量,则称之为外部耦合。C语言中的extern类型变量就是一种外部耦合。

4. 控制耦合

一个模块通过传送参数和控制信息来选择控制另一个模块的功能,就是控制耦合。控制耦合最常见的方式就是接口调用。

5. 标记耦合

6. 数据耦合

7. 非直接耦合

订阅分发是程序编写常用的设计模式,回调,QT中的信号槽本质都是订阅模式。两个模块之间可以直接交互,也可以借助第三者来实现交互。下面将展示一种借助第三者来实现模块之间的交互。

messager.hpp

#ifndef _SELF_MAMESSAGE__ #define _SELF_MAMESSAGE__ #include  #include  #include  #include  #include  #include  #include  #include  #include  class RWLock { std::mutex _mutex; std::condition_variable _readcv, _writecv; std::atomic_bool _iswritting; std::atomic_int _readcount; public: RWLock() : _iswritting(false) , _readcount(0) {} void lockr() { if(_iswritting) { _mutex.lock(); } _readcount++; } void unlockr() { _readcount--; if(_readcount == 0) { _mutex.unlock(); } } void lockw() { if(_iswritting || _readcount != 0) { _mutex.lock(); } _iswritting = true; } void unlockw() { _iswritting = false; _mutex.unlock(); } }; class SelfMessager { public: SelfMessager() = delete; static void subcribe(const std::string &key, std::function func) { getpubsub_mutex().lockw(); auto &messager_map = get_messager_map(); auto &funcs = messager_map[key]; funcs.push_back(func); getpubsub_mutex().unlockw(); } template static void subcribe(const std::string &key, std::function func) { getpubsub_mutex_p1().lockw(); auto &messager_map = get_messager_map(); auto &funcs = messager_map[key]; funcs.push_back(func); getpubsub_mutex_p1().unlockw(); } template static void subcribe(const std::string &key, std::function func) { getpubsub_mutex_p2().lockw(); auto &messager_map = get_messager_map(); auto &funcs = messager_map[key]; funcs.push_back(func); getpubsub_mutex_p2().unlockw(); } template static void subcribe(const std::string &key, std::function func) { getpubsub_mutex_p3().lockw(); auto &messager_map = get_messager_map(); auto &funcs = messager_map[key]; funcs.push_back(func); getpubsub_mutex_p3().unlockw(); } template static void subcribe(const std::string &key, std::function func) { getpubsub_mutex_p3().lockw(); auto &messager_map = get_messager_map(); auto &funcs = messager_map[key]; funcs.push_back(func); getpubsub_mutex_p3().unlockw(); } template static void subcribe(const std::string &key, std::function func) { getpubsub_mutex_p4().lockw(); auto &messager_map = get_messager_map(); auto &funcs = messager_map[key]; funcs.push_back(func); getpubsub_mutex_p4().unlockw(); } template static void subcribe(const std::string &key, std::function func) { getpubsub_mutex_p5().lockw(); auto &messager_map = get_messager_map(); auto &funcs = messager_map[key]; funcs.push_back(func); getpubsub_mutex_p5().unlockw(); } static void publish(const std::string &key) { getpubsub_mutex().lockr(); auto &messager_map = get_messager_map(); if(messager_map.find(key) == messager_map.end()) { return; } auto &funcs = messager_map[key]; for (const auto &func : funcs) { func(); } getpubsub_mutex().unlockr(); } template static void publish(const std::string &key, const T &value) { getpubsub_mutex_p1().lockr(); auto &messager_map = get_messager_map(); if(messager_map.find(key) == messager_map.end()) { return; } auto &funcs = messager_map[key]; for (const auto &func : funcs) { func(value); } getpubsub_mutex_p1().unlockr(); } template static void publish(const std::string &key, const T0 &value0, const T1 &value1) { getpubsub_mutex_p2().lockr(); auto &messager_map = get_messager_map(); if(messager_map.find(key) == messager_map.end()) { return; } auto &funcs = messager_map[key]; for (const auto &func : funcs) { func(value0, value1); } getpubsub_mutex_p2().unlockr(); } template static void publish(const std::string &key, const T0 &value0, const T1 &value1, const T2 &value2) { getpubsub_mutex_p3().lockr(); auto &messager_map = get_messager_map(); if(messager_map.find(key) == messager_map.end()) { return; } auto &funcs = messager_map[key]; for (const auto &func : funcs) { func(value0, value1, value2); } getpubsub_mutex_p3().unlockr(); } template static void publish(const std::string &key, const T0 &value0, const T1 &value1, const T2 &value2, const T3 &value3) { getpubsub_mutex_p4().lockr(); auto &messager_map = get_messager_map(); if(messager_map.find(key) == messager_map.end()) { return; } auto &funcs = messager_map[key]; for (const auto &func : funcs) { func(value0, value1, value2, value3); } getpubsub_mutex_p4().unlockr(); } template static void publish(const std::string &key, const T0 &value0, const T1 &value1, const T2 &value2, const T3 &value3, const T4 &value4) { getpubsub_mutex_p5().lockr(); auto &messager_map = get_messager_map(); if(messager_map.find(key) == messager_map.end()) { return; } auto &funcs = messager_map[key]; for (const auto &func : funcs) { func(value0, value1, value2, value3, value4); } getpubsub_mutex_p5().unlockr(); } template static void add_server_func(const std::string &key, std::function func) { getserverfunc_mutex().lockw(); auto &server_func = get_server_func(key); if (server_func){ publish("log_fatal", "server_func is already exists, key: " + key); throw std::bad_exception(); } server_func = func; getserverfunc_mutex().unlockw(); } template static bool has_server(const std::string &key) { auto &server_func = get_server_func(key); if (server_func){ return true; } else { return false; } } template static void remove_server_func(const std::string &key) { auto &server_func = get_server_func(key); server_func = std::function(); } template static std::function &get_server_func(const std::string &key) { getserverfunc_mutex().lockr(); auto & server_func_map = get_server_map(); getserverfunc_mutex().unlockr(); return server_func_map[key]; } public: static RWLock& getpubsub_mutex() { static RWLock _pubsubmutex; return _pubsubmutex; } static RWLock& getpubsub_mutex_p1() { static RWLock _pubsubmutex; return _pubsubmutex; } static RWLock& getpubsub_mutex_p2() { static RWLock _pubsubmutex; return _pubsubmutex; } static RWLock& getpubsub_mutex_p3() { static RWLock _pubsubmutex; return _pubsubmutex; } static RWLock& getpubsub_mutex_p4() { static RWLock _pubsubmutex; return _pubsubmutex; } static RWLock& getpubsub_mutex_p5() { static RWLock _pubsubmutex; return _pubsubmutex; } static RWLock& getserverfunc_mutex() { static RWLock _serverfuncmutex; return _serverfuncmutex; } template static void register_server_map() { get_server_map(); } static void register_data_map() { get_messager_map(); } template static void register_data_map() { get_messager_map(); } template static void register_data_map() { get_messager_map(); } template static void register_data_map() { get_messager_map(); } template static void register_data_map() { get_messager_map(); } template static void register_data_map() { get_messager_map(); } template static std::vector get_server_list() { std::vector keys; auto& server_map = get_server_map(); for (auto& server : server_map){ if (server.second){ keys.push_back(server.first); } } return keys; } private: template static std::unordered_map> &get_server_map() { static std::unordered_map> server_func_map; return server_func_map; } static std::unordered_map>> &get_messager_map() { static std::unordered_map>> messager_map; return messager_map; } template static std::unordered_map>> &get_messager_map() { static std::unordered_map>> messager_map; return messager_map; } template static std::unordered_map>> &get_messager_map() { static std::unordered_map>> messager_map; return messager_map; } template static std::unordered_map>> & get_messager_map() { static std::unordered_map>> messager_map; return messager_map; } template static std::unordered_map>> & get_messager_map() { static std::unordered_map>> messager_map; return messager_map; } template static std::unordered_map>> & get_messager_map() { static std::unordered_map>> messager_map; return messager_map; } }; #endif

test_messager.cpp 

#include  #include  #include  #include "messager.hpp" using namespace std; #define MESSAGE_SHOW_RESULR         "show_result" #define MESSAGE_ADD_INT_NUMBER      "add_number" struct TData { std::string str; int   iCount; double dPercent; }; // 消息处理者1 class DataDealerOne { public: static DataDealerOne *GetInstance() { static DataDealerOne s_instande; return &s_instande; } virtual ~DataDealerOne() {} void subcribeMessage() { SelfMessager::subcribe( MESSAGE_SHOW_RESULR, [this](const TData &data) { auto data_info = std::make_shared(); *data_info = data; std::cout << data_info->str << " " << data_info->iCount << " " << data_info->dPercent << std::endl; }); } private: DataDealerOne() { } }; // 消息处理者2 class DataDealerTwo { public: static DataDealerTwo *GetInstance() { static DataDealerTwo s_instande; return &s_instande; } virtual ~DataDealerTwo() {} void subcribeMessage() { SelfMessager::subcribe( MESSAGE_ADD_INT_NUMBER, [this](const int &a, const int &b) { int result = a + b; std::cout << a << " + " << b << " = " << result<< std::endl; }); } private: DataDealerTwo() { } }; class Invoker { public: static Invoker *GetInstance() { static Invoker s_instande; return &s_instande; } void CallOther(const std::string& message) { if (message == MESSAGE_SHOW_RESULR) { //发布消息1 TData data = {"hello world !", 110, 1.234}; SelfMessager::publish(MESSAGE_SHOW_RESULR, data); } else if (message == MESSAGE_ADD_INT_NUMBER) { //发布消息2 int num = 0; SelfMessager::publish(MESSAGE_ADD_INT_NUMBER, 111, 222); std::cout << num << std::endl; } } private: Invoker() {} }; int main(int argc, char* argv[]) { //订阅消息 DataDealerOne::GetInstance()->subcribeMessage(); DataDealerTwo::GetInstance()->subcribeMessage(); //调用 Invoker::GetInstance()->CallOther(MESSAGE_SHOW_RESULR); Invoker::GetInstance()->CallOther(MESSAGE_ADD_INT_NUMBER); return 0; }

运行效果如下:

到此这篇关于C++利用模板实现消息订阅和分发功能的文章就介绍到这了,更多相关C++消息订阅分发内容请搜索0133技术站以前的文章或继续浏览下面的相关文章希望大家以后多多支持0133技术站!

以上就是C++利用模板实现消息订阅和分发功能的详细内容,更多请关注0133技术站其它相关文章!

赞(0) 打赏
未经允许不得转载:0133技术站首页 » C语言