#Qt实现全局观察者模式(多层窗体之间直接传递消息)
近来做项目发现,多个窗体之间要通信真的好麻烦,比如:A调出B,B调出C,那么C给A发消息,那就得经过B转发才能实现。对于两三层窗体,这种方法还可以接受,但嵌套太多就有点烦人了。
基于这个原因,那么要实现的东西就很清楚了,有一个全局类,去直接绑定信号槽关系,在需要触发的时候,通过这个全局类的函数,去相应的触发一下,就可以实现直连通信了。
globalObserver.h
#ifndef GLOBALOBSERVER_H
#define GLOBALOBSERVER_H
#include
#include "obesrverApater.h"
struct relationData
{
QString type;
QObject *reciver;
obesrverApater *obesrverApater;
};
class globalObserver : public QObject
{
Q_OBJECT
public:
//因为是全局只有一个,所以直接单例模式
static globalObserver* getGlobalObserver();
static void release();
static globalObserver *m_pInst;
//绑定
void attach(const QString type, QObject *reciver, const char *method);
//解绑
void detach(const QString type, const QObject* reciver);
//触发
void notify(const QString type);
private:
explicit globalObserver(QObject *parent = 0);
~globalObserver();
private:
QList m_oRelationList;
};
#endif // GLOBALOBSERVER_H
obesrverApater.h
#ifndef OBESRVERAPATER_H
#define OBESRVERAPATER_H
#include
class obesrverApater;
//工厂,方便构造对象
class obesrverApaterFactory
{
public:
static obesrverApaterFactory *getInst();
static void realese();
static obesrverApaterFactory* inst;
obesrverApater* createObesrverApater();
private:
obesrverApaterFactory()
{}
};
//中间层,用来连接信号槽
class obesrverApater : public QObject
{
Q_OBJECT
public:
explicit obesrverApater(QObject *parent = 0);
signals:
void notify();
};
#endif // OBESRVERAPATER_H
接下来就主要看看具体函数的实现了:
obesrverApater *obesrverApaterFactory::createObesrverApater()
{
return new obesrverApater();
}
void globalObserver::attach(const QString type, QObject *reciver, const char *method)
{
obesrverApater *oA = obesrverApaterFactory::getInst()->createObesrverApater();
connect(oA, SIGNAL(notify()), reciver, method);
relationData *data = new relationData();
data->type = type;
data->reciver = reciver;
data->obesrverApater = oA;
m_oRelationList.append(data);
}
- 观察者解绑函数实现
void globalObserver::detach(const QString type, const QObject *reciver)
{
QList::iterator iter = m_oRelationList.begin();
while (iter != m_oRelationList.end())
{
if ((*iter)->type.compare(type) == 0 && (*iter)->reciver == reciver)
{
relationData *data = *iter;
m_oRelationList.removeOne((*iter));
delete data->obesrverApater;
delete data;
return;
}
iter++;
}
}
void globalObserver::notify(const QString type)
{
QList::iterator iter = m_oRelationList.begin();
while (iter != m_oRelationList.end())
{
if ((*iter)->type.compare(type) == 0)
{
emit (*iter)->obesrverApater->notify();
}
iter++;
}
}
globalObserver::~globalObserver()
{
//释放列表数据
QList::iterator iter = m_oRelationList.begin();
while (iter != m_oRelationList.end())
{
delete (*iter)->obesrverApater;
delete *iter;
iter++;
}
}
测试:
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
globalObserver::getGlobalObserver()->attach("haha", this, SLOT(haha()));
globalObserver::getGlobalObserver()->attach("hehe", this, SLOT(hehe()));
QPushButton *p = new QPushButton("haha", this);
connect(p, SIGNAL(clicked()), this, SLOT(onHaha()));
p->setGeometry(10, 10, 200, 40);
}
Widget::~Widget()
{
globalObserver::getGlobalObserver()->detach("haha", this);
globalObserver::getGlobalObserver()->detach("hehe", this);
}
void Widget::haha()
{
QMessageBox::about(this, "", "haha");
}
void Widget::hehe()
{
QMessageBox::about(this, "", "hehe");
}
void Widget::onHaha()
{
globalObserver::getGlobalObserver()->notify("haha");
}
源码下载
升级版-可传参源码下载
备注:自己在空闲时间写的,功能相对简单,有问题欢迎讨论!