一、观察者模式
观察者模式是一种一对多的模式,最贴切的解释就是杂志订阅,每次更新杂志的时候都会通知订阅杂志的人,所以观察者模式要有三个功能:
1.加入观察者到一个表中
2.从表中删除观察者
3.发送通知给表中所有的观察者
4.更新指定消息的内容
二、windows控制台下的例子
#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 FirstDialog : public ObserverBase
{
public:
FirstDialog(){}
~FirstDialog(){}
void Update(void* userdata,int type)
{
//处理指定的消息
switch(type)
{
case kUpdateOutputDir:
{
output_dir_ = *((string*)userdata);
std::cout << "I am in FirstDialog: " << output_dir_ << std::endl;
break;
}
}
}
public:
std::string title_;
std::string output_dir_;
};
class SecondDialog : public ObserverBase
{
public:
SecondDialog(){}
~SecondDialog(){}
void Update(void* userdata,int type)
{
//1.增加判断类型就是只想处理指定的消息
switch(type)
{
case kUpdateOutputDir:
{
output_dir_ = *((string*)userdata);
std::cout << "I am in SecondDialog: " << output_dir_ << std::endl;
break;
}
}
}
public:
std::string title_;
std::string output_dir_;
};
class MainWindow :public ObserverBase
{
public:
MainWindow(){}
~MainWindow(){}
void Update(void* userdata,int type)
{
//处理指定的消息
switch(type)
{
case kUpdateTitle:
{
string title = *((string*)userdata);
//修改输出目录
std::cout << "I am MainWindow: " << title << std::endl;
break;
}
}
}
};
int main(int argc, char* argv[])
{
FirstDialog first_dialog;
SecondDialog second_dialog;
MainWindow 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;
}
运行结果: