场景:
1. 比如在界面开发中,多个窗口之间需要通讯,比较常见的方法就是各个窗口之间包含对其他窗口的引用,之后在需要时通过其他窗口的引用来调用相应的函数获取相应的值;
但是这个确定还是比较明显的,就是会造成窗口之间的依赖和耦合,想想测试或编译某个窗口时另一个窗口必须是没问题的,而另一个窗口编译又依赖它,这样成了反复依赖
导致编译不过或修改其中一个另一个就得相应的改。很麻烦,不好维护。
2. 还有的不切实际的解决办法是在窗口之间发送事件,比如qt得信号或win32的消息,但是这样会造成消息的泛滥,资源的滥用,而且都是主线程来处理事件,何必发事件呢?
解决办法:
1. 使用观察者模式来给观察者发送通知,让观察者及时响应,减少耦合。看实际的例子吧:
main.cpp
/*
* File: main.cpp
*/
#include <list>
#include <stdio.h>
#include <time.h>
#include <string>
#include <iostream>
using namespace std;
enum NotifyType
{
kUpdateOutputDir = 0,
kUpdateTitle
};
class Observer;
/**
* 1.抽象父类,不能实例化,目标.
*/
class Subject
{
public:
virtual ~Subject()
{
}
virtual void Attach(Observer* observer);
virtual void Detach(Observer* observer);
virtual void Notify(void *userdata,int type);
protected:
Subject()
{
}
private:
list<Observer*> observers_;
};
/**
* 1.抽象父类,不能实例化,观察者.
*/
class Observer
{
public:
virtual ~Observer()
{
}
virtual void Update(void* userdata,int type)
{
}
protected:
Observer()
{
}
private:
};
//Subject
void Subject::Attach(Observer* observer)
{
observers_.push_back(observer);
}
void Subject::Detach(Observer* observer)
{
observers_.remove(observer);
}
void Subject::Notify(void *userdata,int type)
{
list<Observer*>::iterator theIterator;
for (theIterator = observers_.begin(); theIterator != observers_.end();
theIterator++)
{
(*theIterator)->Update(userdata,type);
}
}
class DhDialog : public Subject, public Observer
{
public:
DhDialog(){}
~DhDialog(){}
void Update(void* userdata,int type)
{
//1.增加判断类型就是只想处理指定的消息
switch(type)
{
case kUpdateOutputDir:
{
output_dir_ = *((string*)userdata);
std::cout << "I am in DhDialog: " << output_dir_ << std::endl;
break;
}
}
}
std::string title_;
std::string output_dir_;
};
class DhOutputWindow : public Subject, public Observer
{
public:
DhOutputWindow(){}
~DhOutputWindow(){}
void Update(void* userdata,int type)
{
//1.增加判断类型就是只想处理指定的消息
switch(type)
{
case kUpdateTitle:
{
string title = *((string*)userdata);
//修改输出目录
std::cout << "I am DhOutputWindow: " << title << std::endl;
break;
}
}
}
};
int main(int argc, char* argv[])
{
DhDialog dialog;
DhOutputWindow output_window_;
//1.互相监听,注意,这里是动态添加监听,并不是互相之间直接引用各自的对象.
dialog.Attach(&output_window_);
output_window_.Attach(&dialog);
dialog.title_ = "I am infoworld";
dialog.Notify(&dialog.title_,kUpdateTitle);//通知OutputWindow
string output = "C:\\";
output_window_.Notify(&output,kUpdateOutputDir);//通知Dialog
}
输出:
I am DhOutputWindow: I am infoworld
I am in DhDialog: C:\