消息总线

对象间只通过消息来联系,不通过直接的依赖或者关联。消息总线将复杂的关系简化,降低复杂度。

消息总线关键技术

1)通用的消息定义

让所有额对象都通过消息来联系,定义一种通用的消息格式

2)消息的注册

让所有对象都可以注册感兴趣的消息

3)消息分发

通过消息总线分发消息,让所有的接受者都能接收到并处理消息

通用消息的定义

消息的构成=消息的主题+泛型函数

消息主题:用于对消息接受者进行分组,只有对主题感兴趣的接受者,才可以收到消息

泛型函数:用于消息的接收者,所有具备该函数的对象都可以接收消息,std::function<R(Args...)>

消息注册

告诉总线,该对象对某种消息感兴趣,希望接收到某种主题和类型的消息。总线内部维护了一个消息列表,需要发送消息时,遍历这个列表,查找是否有合适的消息和消息接收者,找到合适的接收者后再广播消息。

1.lambda表达式转换为std::function

2.保存注册的消息

消息分发

主题对象希望接收者对象收到消息时,会通过消息总线发送消息,消息的本质是std::function,在发送消息前先创建消息,创建后再发送,消息总线会查找内部的容器,看看那些对象对这个消息感兴趣,只有注册了这个消息的对象才能收到消息。

消息总线的设计思想

function_traits:

#pragma once
#include<functional>
#include<tuple>

template<typename T>
struct function_traits;

template<typename Ret,typename... Args>
struct function_traits<Ret(Args...)>
{
public:
    enum {arity=sizeof...(Args) };
    typedef Ret function_type(Args...);
    typedef Ret return_type;

using stl_function_type = std::function<function_type>;

typedef Ret(*pointer)(Args...);

template<size_t I>
    struct args {
        static_assert(I < arity, "index is out of range");
        using type = typename std::tuple_element < I, std::tuple<Args...>>::type;
    };
};
template<typename Ret, typename... Args>
struct function_traits<Ret(*)(Args...)>:function_traits<Ret(Args...)>
{

};
template<typename Ret, typename... Args>
struct function_traits<std::function<Ret(Args...)>> :function_traits<Ret(Args...)>
{

};

#define FUNCTION_TRAITS(...)\
template<typename ReturnType, typename ClassType, typename ... Args>\
struct function_traits<ReturnType(ClassType::*)(Args...)>:function_traits<ReturnType(Args...)>{ };\

FUNCTION_TRAITS()
/*
FUNCTION_TRAITS(const)
FUNCTION_TRAITS(volatile)
FUNCTION_TRAITS(const volatile)*/
/*
template<typename Callable>
struct function_traits :function_traits<decltype(&(Callable::(operator())))> {};*/

/*
template<typename Function>
typename function_traits<Function>::stl_function_type to_function(const Function & lambda) {
    return static_cast<typename function_traits<Function>::stl_function_type>(lambda);
}*/

template<typename Function>
typename function_traits<Function>::stl_function_type to_function(Function && la) {
    return static_cast<typename function_traits<Function>::stl_function_type>(std::forward<Function>(la));
}
/*
template<typename Function>
typename function_traits<Function>::pointer to_function(const Function & lambda) {
    return static_cast<typename function_traits<Function>::pointer>((lambda));
}*/

messagebus:

#pragma once
#include"function_traits.h"
#include"any.h"
#include<string>
#include<map>

class MessageBus {
public:
    template<typename F>
    void Attach(F&& f, const std::string& strTopic = "") {
        auto func = to_function(std::forward<F>(f));
        Add(strTopic, std::move(func));
    }
    template<typename R>
    void sendReq(const std::string& strTopic = "") {
        using function_type = std::function<R()>;
        std::string strMsgType = strTopic + typeid(function_type).name();
        auto Range = m_map.equal_range(strMsgType);
        for (Iterator it = Range.first; it!= Range.second; it++) {
            auto f = it->second.AnyCast<function_type>();
            f();
        }

}
    template<typename R,typename ... Args>
    void sendReq(Args ... args,const std::string& strTopic = "") {
        using function_type = std::function<R(Args...)>;
        std::string strMsgType = strTopic + typeid(function_type).name();
        auto Range = m_map.equal_range(strMsgType);
        for (Iterator it = Range.first; it !=Range.second; it++) {
            auto f = it->second.AnyCast<function_type>();
            f(std::forward<Args>(args)...);
        }

}
    template<typename R, typename ... Args>
    void Remove(Args ... args, const std::string& strTopic = "") {
        using function_type = std::function<R(args)>;
        std::string strMsgType = strTopic + typeid(function_type).name();
        auto Range = m_map.equal_range(strMsgType);
        m_map.erase(Range.first,Range.second);
    }
private:
    template<typename F>
    void Add(const std::string& strTopic, F&& f) {
        const std::string strMsgType = strTopic + typeid(f).name();
        std::pair<std::string, Any> p(strMsgType, std::forward<F>(f));
        m_map.insert(std::move(p));
    }
    std::multimap<std::string, Any> m_map;
    typedef std::multimap<std::string, Any>::iterator Iterator;

};

c++11-消息总线库相关推荐

  1. C++11的消息总线

    一.什么是消息总线 在大规模的软件开发过程中,对象很多,关联关系非常复杂,如果没有统一的.简洁的方法去管理这些对象关系,会导致对象之间交互困难,后期难以维护. 基于消息总线技术可以解决这些问题.在消息 ...

  2. 消息总线(MQ)知多少

    1 什么时候用MQ? 1.1 MQ的基本概念   消息总线(Message Queue,MQ),是一种跨进程的通信机制,用于在上下游之间传递消息.MQ是一种常见的上下游"逻辑解耦+物理解耦& ...

  3. Spring Cloud(十一)高可用的分布式配置中心 Spring Cloud Bus 消息总线集成(RabbitMQ)

    上一篇文章,留了一个悬念,Config Client 实现配置的实时更新,我们可以使用 /refresh 接口触发,如果所有客户端的配置的更改,都需要手动触发客户端 /refresh ,当服务越来越多 ...

  4. java B2B2C电子商务平台分析之十一------配置中心和消息总线

    Spring Cloud Bus Spring cloud bus通过轻量消息代理连接各个分布的节点.这会用在广播状态的变化(例如配置变化)或者其他的消息指令.Spring bus的一个核心思想是通过 ...

  5. (四)spring cloud微服务分布式云架构-配置中心和消息总线(配置中心终结版)...

    Spring Cloud Bus Spring cloud bus通过轻量消息代理连接各个分布的节点.这会用在广播状态的变化(例如配置变化)或者其他的消息指令.Spring bus的一个核心思想是通过 ...

  6. Spring Cloud构建微服务架构(七)消息总线(续:Kafka)

    Spring Cloud Bus除了支持RabbitMQ的自动化配置之外,还支持现在被广泛应用的Kafka.在本文中,我们将搭建一个Kafka的本地环境,并通过它来尝试使用Spring Cloud B ...

  7. linux 进程间通信 dbus-glib【实例】详解二(下) 消息和消息总线(ListActivatableNames和服务器的自动启动)(附代码)

    linux 进程间通信 dbus-glib[实例]详解一(附代码)(d-feet工具使用) linux 进程间通信 dbus-glib[实例]详解二(上) 消息和消息总线(附代码) linux 进程间 ...

  8. linux 进程间通信 dbus-glib【实例】详解二(上) 消息和消息总线(附代码)

    linux 进程间通信 dbus-glib[实例]详解一(附代码)(d-feet工具使用) linux 进程间通信 dbus-glib[实例]详解二(上) 消息和消息总线(附代码) linux 进程间 ...

  9. 分布式消息总线,基于.NET Socket Tcp的发布-订阅框架之离线支持,附代码下载

    一.分布式消息总线以及基于Socket的实现 在前面的分享一个分布式消息总线,基于.NET Socket Tcp的发布-订阅框架,附代码下载一文之中给大家分享和介绍了一个极其简单也非常容易上的基于.N ...

  10. JAVA 多用户商城系统b2b2c---配置中心和消息总线

    Spring Cloud Bus 电子商务平台源码请加企鹅求求:一零三八七七四六二六. Spring cloud bus通过轻量消息代理连接各个分布的节点.这会用在广播状态的变化(例如配置变化)或者其 ...

最新文章

  1. oracle触发器初始化,oracle – 触发器无法初始化变量
  2. 李飞飞:物体识别之后,计算机视觉的进展、目标和前景何在?
  3. 60条令你大吃一惊的小常识,很有用
  4. Docker 获取镜像 - 一
  5. 什么是Cadence call
  6. 【翻译】在Ext JS和Sencha Touch中创建自己定义布局
  7. 039_MySQL_多表查询
  8. 服务器系统授权,授权方案说明
  9. String(+) vs StringBuffer(append)
  10. Utility Lambda
  11. Adobe Acrobat Reader离线安装包下载
  12. 什么是自动化测试?为什么要自动化测试?怎么做?
  13. html 日期选择器 ie8,兼容IE8的简单jQuery日期选择器插件
  14. 阻抗测试仪软件,超声波换能器阻抗测试仪
  15. vs(c++)修改图标
  16. Halcon——颜色检测
  17. 七、 标准型、基、基解、基可行解、可行基
  18. 网规配置案例分析——国庆
  19. win7怎么设置热点让手机连接?热点共享网络的方法
  20. 用大顶堆取出一个数组中最小的k个数

热门文章

  1. 小象学院0基础python视频_2018小象学院《分布式爬虫实战》第二期视频教程
  2. 星巴克中国组织架构调整,要向瑞幸咖啡学习?
  3. 论坛系统的设计与实现
  4. python祝福代码_Python 将 QQ 好友头像生成祝福语的实现代码
  5. Java进阶学习第十二天——JSP JavaBean EL
  6. 实例讲解linux用户,组,文件目录权限
  7. php pdo attr_emulate_prepares,php – 将PDO :: ATTR_EMULATE_PREPARES更改为FALSE并获取“无效参数编号”错误...
  8. 中国羽绒服行业产销需求与投资预测分析报告
  9. Python爬取彩票双色球并存到把数据excel表格里
  10. 蓝牙5.2新特性 - Enhance ATT