C++利用模板实现消息订阅和分发-创新互联

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

创新互联公司2013年至今,先为华龙等服务建站,华龙等地企业,进行企业商务咨询服务。为华龙企业网站制作PC+手机+微官网三网同步一站式服务解决您的所有建站问题。

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#includeclass 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::functionfunc) {
        getpubsub_mutex().lockw();
        auto &messager_map = get_messager_map();
        auto &funcs = messager_map[key];
        funcs.push_back(func);
        getpubsub_mutex().unlockw();
    }

    templatestatic void subcribe(const std::string &key, std::functionfunc) {
        getpubsub_mutex_p1().lockw();
        auto &messager_map = get_messager_map();
        auto &funcs = messager_map[key];
        funcs.push_back(func);
        getpubsub_mutex_p1().unlockw();
    }

    templatestatic void subcribe(const std::string &key, std::functionfunc) {
        getpubsub_mutex_p2().lockw();
        auto &messager_map = get_messager_map();
        auto &funcs = messager_map[key];
        funcs.push_back(func);
        getpubsub_mutex_p2().unlockw();
    }

    templatestatic void subcribe(const std::string &key, std::functionfunc) {
        getpubsub_mutex_p3().lockw();
        auto &messager_map = get_messager_map();
        auto &funcs = messager_map[key];
        funcs.push_back(func);
        getpubsub_mutex_p3().unlockw();
    }

    templatestatic void subcribe(const std::string &key, std::functionfunc) {
        getpubsub_mutex_p3().lockw();
        auto &messager_map = get_messager_map();
        auto &funcs = messager_map[key];
        funcs.push_back(func);
        getpubsub_mutex_p3().unlockw();
    }

    templatestatic void
    subcribe(const std::string &key, std::functionfunc) {
        getpubsub_mutex_p4().lockw();
        auto &messager_map = get_messager_map();
        auto &funcs = messager_map[key];
        funcs.push_back(func);
        getpubsub_mutex_p4().unlockw();
    }

    templatestatic void subcribe(const std::string &key,
                         std::functionfunc) {
        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();
    }

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

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

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

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

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

    templatestatic void add_server_func(const std::string &key, std::functionfunc) {
        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();
    }

    templatestatic bool has_server(const std::string &key) {
        auto &server_func = get_server_func(key);
        if (server_func){
            return true;
        } else {
            return false;
        }
    }

    templatestatic void remove_server_func(const std::string &key) {
        auto &server_func = get_server_func(key);
        server_func = std::function();
    }

    templatestatic 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;
    }


    templatestatic void register_server_map() {
        get_server_map();
    }

    static void register_data_map() {
        get_messager_map();
    }

    templatestatic void register_data_map() {
        get_messager_map();
    }

    templatestatic void register_data_map() {
        get_messager_map();
    }

    templatestatic void register_data_map() {
        get_messager_map();
    }

    templatestatic void register_data_map() {
        get_messager_map();
    }

    templatestatic void register_data_map() {
        get_messager_map();
    }

    templatestatic std::vectorget_server_list() {
        std::vectorkeys;
        auto& server_map = get_server_map();
        for (auto& server : server_map){
            if (server.second){
                keys.push_back(server.first);
            }
        }
        return keys;
    }

private:
    templatestatic 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;
    }

    templatestatic std::unordered_map>>&get_messager_map() {
        static std::unordered_map>>messager_map;
        return messager_map;
    }

    templatestatic std::unordered_map>>&get_messager_map() {
        static std::unordered_map>>messager_map;
        return messager_map;
    }

    templatestatic std::unordered_map>>&
    get_messager_map() {
        static std::unordered_map>>messager_map;
        return messager_map;
    }

    templatestatic std::unordered_map>>&
    get_messager_map() {
        static std::unordered_map>>messager_map;
        return messager_map;
    }

    templatestatic 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;
}

运行效果如下:

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


标题名称:C++利用模板实现消息订阅和分发-创新互联
文章路径:http://abwzjs.com/article/cdgddd.html