场景:多窗口之间的通讯,使用观察者模式来给观察者发送通知消息,让观察者及时响应信息,减少窗口之间包含其他窗口的引用,减少耦合。下面看一个模型图
上图:两个模式对话框和主窗口之间的关系,模式对话框只和主窗口之间进行绑定,两个模式对话框之间没有直接的关系,它们之间要进行通讯,可以通过主窗口来进行消息的转发 ,避免多个窗口之间相互引用,造成意外的情况发生。
#include <stdio.h>
#include <stdlib.h>
#include <list>
#include <string>
#include <iostream>
using namespace std;
enum NotifyType
{
kUpdateOutputDir = 0,
kUpdateTitle
};
*/
/**
* 1.抽象父类,不能实例化,观察者.
*/
class ObserverBase
{
public:
ObserverBase()
{
}
virtual ~ObserverBase()
{
}
virtual void Attach(ObserverBase* observer);
virtual void Detach(ObserverBase* observer);
virtual void Notify(void *userdata,int type);
virtual void Update(void* userdata,int type)
{
}
private:
list<ObserverBase*> observer_list_;
};
//Subject
void ObserverBase::Attach(ObserverBase* observer)
{
observer_list_.push_back(observer); //把观察者加入到队列中,添加绑定
}
void ObserverBase::Detach(ObserverBase* observer)
{
observer_list_.remove(observer); //把观察者从队列移除,解除绑定
}
void ObserverBase::Notify(void *userdata,int type)
{
list<ObserverBase*>::iterator it;
for (it = observer_list_.begin(); it != observer_list_.end();
it++)
{
(*it)->Update(userdata,type);
}
}
class MqjFirstDialog : public ObserverBase
{
public:
MqjFirstDialog(){}
~MqjFirstDialog(){}
void Update(void* userdata,int type)
{
//处理指定的消息
switch(type)
{
case kUpdateOutputDir:
{
output_dir_ = *((string*)userdata);
std::cout << "I am in MqjFirstDialog: " << output_dir_ << std::endl;
break;
}
}
}
public:
std::string title_;
std::string output_dir_;
};
class MqjSecondDialog : public ObserverBase
{
public:
MqjSecondDialog(){}
~MqjSecondDialog(){}
void Update(void* userdata,int type)
{
//1.增加判断类型就是只想处理指定的消息
switch(type)
{
case kUpdateOutputDir:
{
output_dir_ = *((string*)userdata);
std::cout << "I am in MqjSecondDialog: " << output_dir_ << std::endl;
break;
}
}
}
public:
std::string title_;
std::string output_dir_;
};
class MqjMainWindow :public ObserverBase
{
public:
MqjMainWindow(){}
~MqjMainWindow(){}
void Update(void* userdata,int type)
{
//处理指定的消息
switch(type)
{
case kUpdateTitle:
{
string title = *((string*)userdata);
//修改输出目录
std::cout << "I am MqjMainWindow: " << title << std::endl;
break;
}
}
}
};
int main(int argc, char* argv[])
{
MqjFirstDialog first_dialog;
MqjSecondDialog second_dialog;
MqjMainWindow main_window_;
//1.互相监听,注意,这里是动态添加监听,并不是互相之间直接引用各自的对象.
first_dialog.Attach(&main_window_);
main_window_.Attach(&first_dialog);
first_dialog.title_ = "I am first";
first_dialog.Notify(&first_dialog.title_,kUpdateTitle);//通知MainWindow
string output = "D:\\first-dialog\\common";
main_window_.Notify(&output,kUpdateOutputDir);//通知firstDialog
first_dialog.Detach(&main_window_);//解除 first_dialog 和main_window之间的绑定
main_window_.Detach(&first_dialog);
second_dialog.Attach(&main_window_);
main_window_.Attach(&second_dialog);
second_dialog.title_ = "I am second";
second_dialog.Notify(&second_dialog.title_,kUpdateTitle);//通知MainWindow
output = "D:\\second-dialog\\common";
main_window_.Notify(&output,kUpdateOutputDir);//通知secondDialog
return 0;
}
运行结果: