该耦合器提供了一种事件机制,可以实现应用程序中松散耦合组件之间的通信。这种机制基于事件聚合器服务,允许发布者和订阅者通过事件进行通信,并且彼此之间仍然没有直接引用。简单来说就是提供了一个多播发布/订阅功能。
看上图了解事件耦合器。
Qt中自带的信号/槽也是一种解耦机制,但是当项目做大后要写好多connect来链接关系,有了事件耦合器后就不需要connect了。
1、创建事件
testeventargs.h:
#ifndef TESTEVENTARGS_H
#define TESTEVENTARGS_H
#include "Event/baseeventargs.h"
class TestEventArgs : public BaseEventArgs
{
public:
explicit TestEventArgs();
int getId() const;
void setId(int value);
QString getName() const;
void setName(const QString &value);
QString toString();
private:
int id;
QString name;
};
#endif // TESTEVENTARGS_H
testeventargs.cpp
#include "testeventargs.h"
TestEventArgs::TestEventArgs() : BaseEventArgs()
{
}
int TestEventArgs::getId() const
{
return id;
}
void TestEventArgs::setId(int value)
{
id = value;
}
QString TestEventArgs::getName() const
{
return name;
}
void TestEventArgs::setName(const QString &value)
{
name = value;
}
QString TestEventArgs::toString()
{
return QString("id=%1,name=%2").arg(id).arg(name);
}
2、订阅事件
//订阅
void Widget::on_btnSub_clicked()
{
Function<void(TestEventArgs)> func(this, &Widget::dealEvent);
EventAggregator::GetEvent<TestEvent>()->Subscribe(func);
}
//处理事件
void Widget::dealEvent(TestEventArgs args)
{
ui->label->setText(args.toString());
}
3、发布事件
//发布
void Widget::on_btnPub_clicked()
{
TestEventArgs args;
args.setId(1);
args.setName("Test Event");
EventAggregator::GetEvent<TestEvent>()->Puslish(args);
}
这样,一个发布/订阅的事件就完成了,也可以在任何时候取消事件注册,只需要调用Unsubscribe方法即可
EventAggregator::GetEvent<TestEvent>()->Unsubscribe(func);
源码:
baseeventargs.h
#ifndef DKBASEEVENTARGS_H
#define DKBASEEVENTARGS_H
#include <QFuture>
/**
* @brief 事件参数基类
*/
class BaseEventArgs
{
public:
~BaseEventArgs()
{
}
bool isSync() const
{
return m_sync;
}
void setSync(bool sync)
{
m_sync = sync;
}
private:
/**
* @brief 是否同步执行事件 true-同步 false-异步
* 注:发布和订阅同一线程中既可以选择同步也可以选择异步,否则只能选择异步;异步调用中使用QMetaObject::invokeMethod
*/
bool m_sync = true;
};
#endif // DKBASEEVENTARGS_H
eventaggregator.h
#ifndef DKEVENTAGGREGATOR_H
#define DKEVENTAGGREGATOR_H
#include <QObject>
#include <QMap>
#include <QString>
#include <QMutex>
/**
* @brief 事件耦合器
*/
class EventAggregator : public QObject
{
Q_OBJECT
/**
* @brief 事件对象map(key-事件类型名,value-事件对象)
*/
static QMap<QString,QObject*> m_map;
/**
* @brief 互斥锁
*/
static QMutex *m_pMutex;
public:
explicit EventAggregator(QObject *parent = nullptr);
/**
* @brief 获取模板类型的事件对象
* @return 指定类型事件对象
*/
template<typename EventType>
static EventType* GetEvent()
{
EventType *pEvent;
QString className = typeid (EventType).name();
if(m_map.contains(className))
{
pEvent = static_cast<EventType*>(m_map[className]);
}
else
{
pEvent = new EventType;
m_pMutex->lock();
m_map.insert(className,pEvent);
m_pMutex->unlock();
}
return pEvent;
}
};
#endif // DKEVENTAGGREGATOR_H
eventaggregator.cpp
#include "eventaggregator.h"
EventAggregator::EventAggregator(QObject *parent) : QObject(parent)
{
}
QMap<QString,QObject*> EventAggregator::m_map = QMap<QString,QObject*>();
QMutex* EventAggregator::m_pMutex = new QMutex();
eventbase.h
#ifndef DKEVENTBASE_H
#define DKEVENTBASE_H
#include <QObject>
/**
* @brief 事件基类
*/
class EventBase : public QObject
{
Q_OBJECT
public:
explicit EventBase(QObject *parent = nullptr);
};
#endif // DKEVENTBASE_H
eventbase.cpp
#include "eventbase.h"
EventBase::EventBase(QObject *parent) : QObject(parent)
{
}
function.h
#ifndef DKFUNCTION_H
#define DKFUNCTION_H
#include <QUuid>
#include <functional>
/**
* @brief函数封装类
*/
template<class T>
class Function
{
private:
QUuid m_uuid;
bool m_isEnable = true;
public:
std::function<T> call;
public:
Function(): m_uuid(QUuid::createUuid())
{
}
Function(std::function<T> func): Function()
{
this->call = func;
}
template<typename t1, typename t2>
Function(t1 pOwner, t2 pFunc): Function()
{
call = std::bind(pFunc, pOwner, std::placeholders::_1);
}
bool operator==(const Function& func)
{
return this->m_uuid == func.m_uuid;
}
Function& operator=(const std::function<T>& func)
{
call = func;
return *this;
}
/**
* @brief 设置成员变量函数
* @param pOwner 成员函数所属对象指针
* @param pFunc 成员函数指针
*/
template<typename t1, typename t2>
void setMemberFunction(t1 pOwner, t2 pFunc)
{
call = std::bind(pFunc, pOwner, std::placeholders::_1);
}
/**
* @brief 设置普通函数、匿名函数和std::function类型仿函数
* @param pFunc 函数指针
*/
template<typename t1>
void setFunction(t1 pFunc)
{
call = pFunc;
}
bool isEnable() const
{
return m_isEnable;
}
void setIsEnable(bool isEnable)
{
m_isEnable = isEnable;
}
};
#endif // DKFUNCTION_H
pubsubevent.h
#ifndef DKPUBSUBEVENT_H
#define DKPUBSUBEVENT_H
#include <QList>
#include <functional>
#include <QtConcurrent>
#include "Event/eventbase.h"
#include "Event/function.h"
#include "Event/baseeventargs.h"
/**
* @brief 订阅发布事件
*/
template <class TPayload>
class PubSubEvent: public EventBase
{
typedef Function<void(TPayload)> FuncType;
private:
QList<FuncType> m_list;
QMutex m_mutex;
public:
PubSubEvent(QObject* parent = nullptr): EventBase(parent)
{
}
PubSubEvent& operator+=(FuncType func)
{
m_mutex.lock();
if(!m_list.contains(func))
{
m_list.append(func);
}
m_mutex.unlock();
return *this;
}
PubSubEvent& operator-=(FuncType func)
{
m_mutex.lock();
m_list.removeOne(func);
m_mutex.unlock();
return *this;
}
void operator()(TPayload payload, bool isSync = true)
{
BaseEventArgs& event = static_cast<BaseEventArgs&>(payload);
event.setSync(isSync);
for(auto dkFunc : m_list)
{
if(isSync)
{
dkFunc.call(payload);
}
else
{
QtConcurrent::run(dkFunc.call, payload);
}
}
}
/**
* @brief 发布事件
* @param payload 事件载体,即事件参数
* @param isSync 是否同步执行
*/
void Puslish(TPayload payload, bool isSync = true)
{
BaseEventArgs& eventArgs = static_cast<BaseEventArgs&>(payload);
eventArgs.setSync(isSync);
for(auto dkFunc : m_list)
{
if(dkFunc.isEnable())
{
if(isSync)
{
dkFunc.call(payload);
}
else
{
QtConcurrent::run(dkFunc.call, payload);
}
}
}
}
/**
* @brief 订阅事件
* @param func 处理事件的函数
*/
void Subscribe(FuncType& func)
{
m_mutex.lock();
if(!m_list.contains(func))
{
m_list.append(func);
}
m_mutex.unlock();
}
/**
* @brief 取消订阅事件
* @param func 订阅事件的函数
*/
void Unsubscribe(FuncType& func)
{
m_mutex.lock();
m_list.removeOne(func);
m_mutex.unlock();
}
};
#endif // DKPUBSUBEVENT_H
源码下载地址:
本文含有隐藏内容,请 开通VIP 后查看