<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
解耦是編寫程式所遵循的基本原則之一,多型是提高程式靈活性的重要方法。C++語言支援過載,模板,虛擬函式等特性,為編寫高效能可延伸的程式提供了利器。編寫大型專案時,免不了需要各個模組之間相互呼叫,從而產生了模組之間的耦合。不同模組之間的關係稱之為耦合,耦合程度由高到底可以分為以下幾類:
1. 內容耦合
內容耦合常見情形如下:
1)一個模組直接存取另一個模組的內容
2)一個模組不通過正常入口轉到另一個模組
3)兩個模組有部分程式程式碼重疊,常見在組合語言中
4)一個模組有多個入口
2. 公共耦合
若模組都存取同一個公共資料環境,則稱他們是公共耦合。
3. 外部耦合
模組通過非引數傳遞的方式存取同一個全域性變數,則稱之為外部耦合。C語言中的extern型別變數就是一種外部耦合。
4. 控制耦合
一個模組通過傳送引數和控制資訊來選擇控制另一個模組的功能,就是控制耦合。控制耦合最常見的方式就是介面呼叫。
5. 標記耦合
6. 資料耦合
7. 非直接耦合
訂閱分發是程式編寫常用的設計模式,回撥,QT中的訊號槽本質都是訂閱模式。兩個模組之間可以直接互動,也可以藉助第三者來實現互動。下面將展示一種藉助第三者來實現模組之間的互動。
messager.hpp
#ifndef _SELF_MAMESSAGE__ #define _SELF_MAMESSAGE__ #include <map> #include <unordered_map> #include <functional> #include <string> #include <vector> #include <mutex> #include <atomic> #include <thread> #include <condition_variable> 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<void()> func) { getpubsub_mutex().lockw(); auto &messager_map = get_messager_map(); auto &funcs = messager_map[key]; funcs.push_back(func); getpubsub_mutex().unlockw(); } template<typename T> static void subcribe(const std::string &key, std::function<void(const T &)> func) { getpubsub_mutex_p1().lockw(); auto &messager_map = get_messager_map<T>(); auto &funcs = messager_map[key]; funcs.push_back(func); getpubsub_mutex_p1().unlockw(); } template<typename T0, typename T1> static void subcribe(const std::string &key, std::function<void(const T0 &, const T1 &)> func) { getpubsub_mutex_p2().lockw(); auto &messager_map = get_messager_map<T0, T1>(); auto &funcs = messager_map[key]; funcs.push_back(func); getpubsub_mutex_p2().unlockw(); } template<typename T0, typename T1, typename T2> static void subcribe(const std::string &key, std::function<void(const T0 &, const T1 &, const T2 &)> func) { getpubsub_mutex_p3().lockw(); auto &messager_map = get_messager_map<T0, T1, T2>(); auto &funcs = messager_map[key]; funcs.push_back(func); getpubsub_mutex_p3().unlockw(); } template<typename T0, typename T1, typename T2> static void subcribe(const std::string &key, std::function<void(const T0 &, const T1 &, T2 &)> func) { getpubsub_mutex_p3().lockw(); auto &messager_map = get_messager_map<T0, T1, T2>(); auto &funcs = messager_map[key]; funcs.push_back(func); getpubsub_mutex_p3().unlockw(); } template<typename T0, typename T1, typename T2, typename T3> static void subcribe(const std::string &key, std::function<void(const T0 &, const T1 &, const T2 &, const T3 &)> func) { getpubsub_mutex_p4().lockw(); auto &messager_map = get_messager_map<T0, T1, T2, T3>(); auto &funcs = messager_map[key]; funcs.push_back(func); getpubsub_mutex_p4().unlockw(); } template<typename T0, typename T1, typename T2, typename T3, typename T4> static void subcribe(const std::string &key, std::function<void(const T0 &, const T1 &, const T2 &, const T3 &, const T4 &)> func) { getpubsub_mutex_p5().lockw(); auto &messager_map = get_messager_map<T0, T1, T2, T3, T4>(); 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<typename T> static void publish(const std::string &key, const T &value) { getpubsub_mutex_p1().lockr(); auto &messager_map = get_messager_map<T>(); 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<typename T0, typename T1> static void publish(const std::string &key, const T0 &value0, const T1 &value1) { getpubsub_mutex_p2().lockr(); auto &messager_map = get_messager_map<T0, T1>(); 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<typename T0, typename T1, typename T2> 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<T0, T1, T2>(); 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<typename T0, typename T1, typename T2, typename T3> 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<T0, T1, T2, T3>(); 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<typename T0, typename T1, typename T2, typename T3, typename T4> 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<T0, T1, T2, T3, T4>(); 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<typename T> static void add_server_func(const std::string &key, std::function<T> func) { getserverfunc_mutex().lockw(); auto &server_func = get_server_func<T>(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<typename T> static bool has_server(const std::string &key) { auto &server_func = get_server_func<T>(key); if (server_func){ return true; } else { return false; } } template<typename T> static void remove_server_func(const std::string &key) { auto &server_func = get_server_func<T>(key); server_func = std::function<T>(); } template<typename T> static std::function<T> &get_server_func(const std::string &key) { getserverfunc_mutex().lockr(); auto & server_func_map = get_server_map<T>(); 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<typename T> static void register_server_map() { get_server_map<T>(); } static void register_data_map() { get_messager_map(); } template<typename T> static void register_data_map() { get_messager_map<T>(); } template<typename T0, typename T1> static void register_data_map() { get_messager_map<T0, T1>(); } template<typename T0, typename T1, typename T2> static void register_data_map() { get_messager_map<T0, T1, T2>(); } template<typename T0, typename T1, typename T2, typename T3> static void register_data_map() { get_messager_map<T0, T1, T2, T3>(); } template<typename T0, typename T1, typename T2, typename T3, typename T4> static void register_data_map() { get_messager_map<T0, T1, T2, T3, T4>(); } template<typename T> static std::vector<std::string> get_server_list() { std::vector<std::string> keys; auto& server_map = get_server_map<T>(); for (auto& server : server_map){ if (server.second){ keys.push_back(server.first); } } return keys; } private: template<typename T> static std::unordered_map<std::string, std::function<T>> &get_server_map() { static std::unordered_map<std::string, std::function<T>> server_func_map; return server_func_map; } static std::unordered_map<std::string, std::vector<std::function<void()>>> &get_messager_map() { static std::unordered_map<std::string, std::vector<std::function<void()>>> messager_map; return messager_map; } template<typename T> static std::unordered_map<std::string, std::vector<std::function<void(const T &)>>> &get_messager_map() { static std::unordered_map<std::string, std::vector<std::function<void(const T &)>>> messager_map; return messager_map; } template<typename T0, typename T1> static std::unordered_map<std::string, std::vector<std::function<void(const T0 &, const T1 &)>>> &get_messager_map() { static std::unordered_map<std::string, std::vector<std::function<void(const T0 &, const T1 &)>>> messager_map; return messager_map; } template<typename T0, typename T1, typename T2> static std::unordered_map<std::string, std::vector<std::function<void(const T0 &, const T1 &, const T2 &)>>> & get_messager_map() { static std::unordered_map<std::string, std::vector<std::function<void(const T0 &, const T1 &, const T2 &)>>> messager_map; return messager_map; } template<typename T0, typename T1, typename T2, typename T3> static std::unordered_map<std::string, std::vector<std::function<void(const T0 &, const T1 &, const T2 &, const T3 &)>>> & get_messager_map() { static std::unordered_map<std::string, std::vector<std::function<void(const T0 &, const T1 &, const T2 &, const T3 &)>>> messager_map; return messager_map; } template<typename T0, typename T1, typename T2, typename T3, typename T4> static std::unordered_map<std::string, std::vector<std::function<void(const T0 &, const T1 &, const T2 &, const T3 &, const T4 &)>>> & get_messager_map() { static std::unordered_map<std::string, std::vector<std::function<void(const T0 &, const T1 &, const T2 &, const T3 &, const T4 &)>>> messager_map; return messager_map; } }; #endif
test_messager.cpp
#include <iostream> #include <string> #include <memory> #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<TData>( MESSAGE_SHOW_RESULR, [this](const TData &data) { auto data_info = std::make_shared<TData>(); *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<int, int>( 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++訊息訂閱分發內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45