前提:1.熟悉了观察者模式,不熟悉看这个观察者模式 2.了解Qt的信号和信号槽。 3.熟悉std::bind()来调用类的方法std::bind调用类方法 4.熟悉模板类的简单使用模板类做基类
1.Qt中的信号和信号槽
- 在Qt中-----准备工作
1.定义A对象, 定义A对象的信号signal-A 2.定义B对象,定义B对象的slot函数 3.connect函数:将A对象发出的signal-A, 和B对象执行的slot函数绑定起来。 - 信号触发
4.A发出信号signal-A 5.B收到signal-A就会执行slot函数
2.本质的解析
3.connect函数执行的动作:其实就是一个B对象订阅signal-A的动作。 4.A发出信号:即代表一个广播的动作,但只有B对象会处理这个信号,因为B对象有订阅这个信号。 5.B收到信号的处理动作,即执行slot()函数
上面的三点加起来就是:消息的订阅,消息的发布,消息的处理。这就是一个观察者模式。
3.通过观察者模式实现信号槽
假设这样一个场景:猫和老鼠的tom和jerry 1.jerry看着tom. 2.tom叫 3.jerry跑 上面三个对应:订阅,发布,处理。即Qt 的connect(), emit ,slot函数
#include "Subject.h"
#include <functional>
#include <iostream>
using std::cout;
using std::endl;
class catObserver {
public:
virtual void onPublish() = 0;
public:
virtual ~catObserver() {}
};
class Jerry : public catObserver {
public:
void onPublish() {
Run();
}
private:
void Run() {
cout << "hear tom miao,jerry run" << endl;
}
};
class Tom {
public:
void subscribe(catObserver* observer) {
obj_list.push_back(observer);
}
void publish() {
cout << "tom miao" << endl;
for (auto tmp: obj_list) {
tmp->onPublish();
}
}
private:
std::vector<catObserver* > obj_list;
};
int main()
{
Tom tom;
Jerry jerry;
tom.subscribe(&jerry);
tom.publish();
return 0;
}
//上面的代码简单的实现了:消息的订阅,发布,和处理。而QT的信号槽不过是观察者模式的升级。 QT的connect() -----------------观察者模式的订阅,把消息和处理函数绑定起来(通过catObserver的虚方法的实现) QT的emit某个signal ----------观察者模式的消息发布 QT的信号槽函数---------------观察者模式的消息处理
简单的封装带有publish,subscribe的基类
#include <vector>
#include <algorithm>
template <typename ObserverType>
class Subject
{
public:
void subscribe(ObserverType* obsver)
{
auto tmp = std::find(obj_list.begin(), obj_list.end(), obsver);
if (tmp == obj_list.end()) {
obj_list.push_back(obsver);
}
}
void unsubscribe(ObserverType* obsver)
{
obj_list.erase(std::remove(obj_list.begin(), obj_list.end(), obsver));
}
template <typename FuncType>
void publish(FuncType func)
{
for (auto obs: obj_list)
{
func(obs);
}
}
private:
std::vector<ObserverType*> obj_list;
};
#include "VistorMode.h"
#include <functional>
#include <iostream>
using std::cout;
using std::endl;
using std::bind;
class catObserver {
public:
virtual void onMiao() = 0;
public:
virtual ~catObserver() {}
};
class Jerry : public catObserver {
public:
void onMiao() {
Run();
}
private:
void Run() {
cout << "hear tom miao,jerry run" << endl;
}
};
class Tom : public Subject<catObserver>
{
public:
void Miao() {
publish(std::bind(&catObserver::onMiao, std::placeholders::_1));
}
};
int main()
{
Tom tom;
Jerry jerry;
tom.subscribe(&jerry);
tom.Miao();
return 0;
}
|