简介
观察者模式(Observer)完美的将观察者和被观察的对象分离开。举个例子,用户界面可以作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上。面向对象设计的一个原则是:系统中的每个类将重点放在某一个功能上,而不是其他方面。一个对象只做一件事情,并且将他做好。观察者模式在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性。
观察者设计模式定义了对象间的一种一对多的依赖关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。
实现方式
观察者模式有很多实现方式,从根本上说,该模式必须包含两个角色:观察者和被观察对象。在刚才的例子中,业务数据是被观察对象,用户界面是观察者。观察者和被观察者之间存在“观察”的逻辑关联,当被观察者发生改变的时候,观察者就会观察到这样的变化,并且做出相应的响应。如果在用户界面、业务数据之间使用这样的观察过程,可以确保界面和数据之间划清界限,假定应用程序的需求发生变化,需要修改界面的表现,只需要重新构建一个用户界面,业务数据不需要发生变化。
代码
#include<iostream>
#include<string>
#include<vector>
using namespace std;
class TV;
class watcher
{
public:
watcher(string n,TV* tv){
name=n;
ptv=tv;
};
void Release();
string name;
TV* ptv;
};
class TV
{
public:
string weather;
void Add(watcher w){watcherList.push_back(w);}
void Remove(int t){
vector<watcher>::iterator it=watcherList.begin();
if(t>=0&&t<watcherList.size())
watcherList.erase(it+t);
}
void Notify(){
vector<watcher>::iterator it;
for(it=watcherList.begin();it<watcherList.end();it++)
it->Release();
}
private:
vector<watcher> watcherList;
};
void watcher::Release()
{
cout<<"To "<<name<<":"<<ptv->weather<<endl;
}
int main()
{
TV* t=new TV;
watcher* user1=new watcher("hsh",t);
watcher* user2=new watcher("hpy",t);
watcher* user3=new watcher("py",t);
watcher* user4=new watcher("wsc",t);
t->weather="多云有小雨";
t->Add(*user1);
t->Add(*user2);
t->Add(*user3);
t->Add(*user4);
t->Notify();
cout<<endl;
t->Remove(1);
t->Notify();
delete user1;
delete user2;
delete user3;
delete user4;
}
优点
1、观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体观察者列表,每一个具体观察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。由于被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。如果被观察者和观察者都被扔到一起,那么这个对象必然跨越抽象化和具体化层次。
2、观察者模式支持广播通讯。被观察者会向所有的登记过的观察者发出通知,
缺点
1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
2、如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察者模式是要特别注意这一点。
3、如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。
4、虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。