QT-观察者模式

观察者模式定义了一对多的依赖关系,当一个对象改变时,它的所有依赖者都会收到通知并自动更新。类似很多人订阅了一个公众号,一旦公众号发送消息,订阅的人都会收到消息。
经典的观察者模式在讲解举例的时候通常会举报纸和订阅者的例子。有一个报纸Newspaper,有一个订阅者类Subscriber。Subscriber可以订阅Newspaper。这样,当Newspaper有了新的内容的时候,Subscriber可以立即得到通知。在这个例子中,观察者是Subscriber,被观察者是Newspaper。在经典的实现代码中,观察者会将自身注册到被观察者的一个容器中。被观察者发生了任何变化的时候,会主动遍历这个容器,依次通知各个观察者。

例如:以不同的显示形式显示某一数据,LCD显示、Label中显示等
1)定义一个被观察对象(目标),其中可以有任意多个观察者,需要提供添加和删除观察者的接口,在被观察对象中定义通知观察者接口
2)定义观察者父类,添加刷新的虚函数接口
3)定义不同的观察者子类,重写刷新接口

实现代码如下:
观察者父类

class Observer : public QWidget
{
public:
    Observer();
	//触发更新的接口
    virtual void update(const int ) const = 0;
};

Label显示数据的子类观察者
.h代码

class ObserverLabel : public Observer
{
public:
    ObserverLabel();
	//触发更新
    void update(const int value) const override;
private:
    QLabel *m_label;
};

.cpp代码

ObserverLabel::ObserverLabel()
{
    m_label = new QLabel("Text");
    QHBoxLayout *layout = new QHBoxLayout();
    layout->addWidget(m_label);
    this->setLayout(layout);
}

void ObserverLabel::update(const int value) const
{
    m_label->setText(QString::number(value));
}

LCD显示的子类观察者
.h代码

class ObserverLcd : public Observer
{
public:
    ObserverLcd();
	//触发更新
    void update(const int value) const override;
private:
    QLCDNumber *m_lcdNum;
};

.cpp代码

ObserverLcd::ObserverLcd()
{
    m_lcdNum = new QLCDNumber();
    QHBoxLayout *layout = new QHBoxLayout;
    layout->addWidget(m_lcdNum);
    this->setLayout(layout);
}

void ObserverLcd::update(const int value) const
{
    m_lcdNum->display(value);
}

被观察对象实现
.h代码

class Subject
{
public:
    Subject();
    //添加观察者
    void addObserver(Observer *obs);
    //移除观察者
    void removeObserver(Observer *obs);
    //触发观察者更新
    void setValue(const int value);
private:
    QList<Observer*> m_observers;
};

.cpp代码

void Subject::addObserver(Observer *obs)
{
    m_observers.append(obs);
}

void Subject::removeObserver(Observer *obs)
{
    m_observers.removeOne(obs);
}

void Subject::setValue(const int value)
{
    for(int i=0; i<m_observers.length(); i++)
    {
        m_observers.at(i)->update(value);
    }
}

调用实现代码
.h代码

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
private slots:
    //添加label观察者
    void on_btnAddLabel_clicked();
    //添加lcd观察者
    void on_btnAddLcd_clicked();
    //触发观察者更新
    void on_spinBox_valueChanged(int arg1);
private:
    Ui::MainWindow *ui;
    Subject m_subject;
};

.cpp代码

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_spinBox_valueChanged(int arg1)
{
    m_subject.setValue(arg1);
}

void MainWindow::on_btnAddLabel_clicked()
{
    ObserverLabel *histogram = new ObserverLabel;
    m_subject.addObserver(histogram);
    ui->hLayout->addWidget(histogram);
}

void MainWindow::on_btnAddLcd_clicked()
{
    ObserverLcd *lcd = new ObserverLcd;
    m_subject.addObserver(lcd);
    ui->hLayout->addWidget(lcd);
}

你可能感兴趣的:(C++)