Qt信号槽与观察者模式

qt的核心机制:信号与槽和设计模式中的观察者模式很类似。
https://www.devbean.net/2012/08/qt-study-road-2-custom-signal-slot
这篇文章讲的很详细,我这就算是做个笔记吧

信号与槽

信号和槽机制是 QT 的核心机制,它是qt自行定义的一种通信机制,独立于标准的 C/C++ 语言。信号与槽的机制,能够设计出解耦(模块化设计)的非常漂亮的程序。

信号(signal)

当某个信号对其客户或所有者发生的内部状态发生改变,信号被一个对象发射。当一个信号被发射时,与其相关联的槽将被立刻执行,就象一个正常的函数调用一样。信号 - 槽机制完全独立于任何 GUI 事件循环。如果存在多个槽与某个信号相关联,那么,当这个信号被发射时,这些槽将会一个接一个地 执行,但是它们执行的顺序将会是随机的、不确定的,我们不能人为地指定哪个先执行、哪 个后执行。

槽(slot)

槽是普通的 C++ 成员函数,可以被正常调用,它们唯一的特殊性就是很多信号可以与其相关联。当与其关联的信号被发射时,这个槽就会被调用。

信号与槽的关联(connect)

通过调用 QObject 对象的 connect 函数来将某个对象的信号与另外一个对象的槽函数相关联,这样当发射者发射信号时,接收者的槽函数将被调用。该函数的定义如下:

bool QObject::connect ( const QObject * sender, const char * signal, const QObject * receiver, const char * memberFunction ) [static]

sender:发送方
signal:发送方发送的信号
receiver:接收方
memberFunction :槽函数
函数的作用就是把发送方sender 对象中的信号 signal 与接收方 receiver 中的 memberFunction 槽函数联系起来。
Ex:点击按钮,退出

#include 
#include 

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QPushButton button("Quit");
    QObject::connect(&button, SIGNAL(clicked()),
                     &app,    SLOT(quit()));
    button.show();

    return app.exec();
}

观察者模式

观察者模式定义了一对多的依赖关系,当一个对象改变时,它的所有依赖者都会收到通知并自动更新。类似很多人订阅了一个公众号,一旦公众号发送消息,订阅的人都会收到消息。
代码摘自:https://www.devbean.net/2012/08/qt-study-road-2-custom-signal-slot/
经典的观察者模式在讲解举例的时候通常会举报纸和订阅者的例子。有一个报纸类Newspaper,有一个订阅者类Subscriber。Subscriber可以订阅Newspaper。这样,当Newspaper有了新的内容的时候,Subscriber可以立即得到通知。在这个例子中,观察者是Subscriber,被观察者是Newspaper。在经典的实现代码中,观察者会将自身注册到被观察者的一个容器中(比如subscriber.registerTo(newspaper))。被观察者发生了任何变化的时候,会主动遍历这个容器,依次通知各个观察者(newspaper.notifyAllSubscribers())。

下面我们看看使用 Qt 的信号槽,如何实现上述观察者模式。注意,这里我们仅仅是使用这个案例,我们的代码并不是去实现一个经典的观察者模式。也就是说,我们使用 Qt 的信号槽机制来获得同样的效果。

#include 

////////// newspaper.h
class Newspaper : public QObject
{
    Q_OBJECT
public:
    Newspaper(const QString & name) :
        m_name(name)
    {
    }

    void send() const
    {//emit 的含义是发出,也就是发出newPaper()信号
        emit newPaper(m_name); 
    }

signals:
    void newPaper(const QString &name) const;

private:
    QString m_name;
};

////////// reader.h
#include 
#include 

class Reader : public QObject
{
    Q_OBJECT
public:
    Reader() {}

public slots:
    void receiveNewspaper(const QString & name) const
    {
        qDebug() << "Receives Newspaper: " << name;
    }
};

////////// main.cpp
#include 

#include "newspaper.h"
#include "reader.h"

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    Newspaper newspaper("Newspaper A");
    Reader reader;
    QObject::connect(&newspaper, SIGNAL(newPaper(QString)),
                     &reader,    SLOT(receiveNewspaper(QString)));
    newspaper.send();

    return app.exec();
}

你可能感兴趣的:(Qt信号槽与观察者模式)