设计模式二十:observer(观察者)——对象行为型模式
observer(观察者)——对象行为型模式
1.意图
定义对象见的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并且自动更新
2.别名
依赖dependen
发布——订阅publish——subscribe
3.动机
将一个系统分割成一系列相互协作的类有一个常见的副作用,需要维护相关对象间的一致性。我们不希望因为需要维护一致性而使各类紧密耦合,这样会影响可重用性。
观察者模式描述了如何建立这种关系。一个目标可以有任意数目的依赖他的观察者。一旦目标状态发生改变,所有观察者都同时得到通知。作为对这个通知的响应,每个观察者都将查询目标以使其状态与目标状态同步。
4.适用性
1)当一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这两者封装在独立的对象中以使他们可以各自独立地改变和复用。
2)当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变。
3)当一个对象必须通知其他对象,而他又不能假定其他对象是谁,换言之,你不希望对象是紧密耦合的。
5.结构

参考:http://www.cnblogs.com/zhxiang/archive/2012/01/12/2320940.html
6.参与者
subject目标
目标知道他的观察者,可以有任意多个观察者观察同一个目标。
提供注册和删除观察者的接口。
observer观察者
为那些在目标发生改变时需要获得通知的对象定义一个更新接口
concreteSubject具体目标
将有关状态存入各concreteObserver对象
当他的状态发生变化时,向各个观察者发出通知
concreteObserver具体观察者
维护一个指向concreteSubject对象的引用
存储有关状态这些状态应用与目标的状态保持一致
实现observer的更新接口以使自身与目标的状态保持一致
7.协作
当concreteSubject发生任何可能导致其观察者和本身状态不一致的改变时,他将通知各个观察者。
在得到一个具体目标的改变通知后,concreteObserver对象可向目标对象查询信息。concreteObserver使用这些信息使他的状态与目标对象的状态一致。
8.效果
1)目标和观察者之间的抽象耦合
一个目标所知道的仅仅是他有一系列的观察者,每个都符合observer的接口,目标不知道具体的观察者属于哪个具体的类。这样耦合最小。
2)支持广播通信
3)意外的更新
因为一个观察者不知道其他观察者的存在,他对可能改变目标的最终代价一无所知。在目标上一个小的操作可能会导致一系列的对观察者以及依赖于这些观察者的那些对象的更新。
9.实现
1)创建目标到其观察者的映射
2)观察多个目标
3)谁触发更新
a)由目标对象的状态设定操作在改变目标对象的状态后自动调用notify
b)让客户负责在适当的时候调用notify
4)对已删除目标的悬挂引用
删除一个目标时应该注意不要再其观察者中遗留对该目标的悬挂引用。
当一个对象被删除时,通知各个观察者将该目标的引用复位。
5)在发出通知前确保目标状态自身是一致的
6)避免特定于观察者的更新协议——推/拉模型
推模型:目标向观察者发送关于改变的详细信息,不管需要与否
拉模型:观察者主动查询
7)显式地指定感兴趣的改变
8)封装复杂的更新语意
定义一个更改管理器changeManager,目标是尽量减少观察者反应其目标的状态变化所需的工作量。
任务:
a)将一个目标映射到他的观察者并提供一个接口来维护这个映射,就不需要由目标来维护其对观察者的引用,反之亦然。
b)定义一个特定的更新策略
c)根据一个目标请求,他更新所有依赖于这个目标的观察者
9)结合目标类和观察者类
10.代码示例
#include<iostream> #include<list> #include<algorithm> using namespace std; class subject; class weather; class observer { public: observer(string s) { n=s; } virtual void update(){} string getName() { return name; } void deleteSub() { m_sub = 0; } protected: string name; weather *m_sub; string n; }; class subject { public: virtual void registeObserver(observer *o){}; virtual void removeObject(observer *o){}; virtual void notifyObserver(){}; ~subject() { list<observer*>::iterator ite; for(ite = _ob.begin(); ite!=_ob.end(); ite++) { (*ite)->deleteSub(); } } protected: list<observer*> _ob; }; class weather:public subject { public: weather() { _ob.clear(); temperature = 0; } void registeObserver(observer *o) { _ob.push_back(o); } void removeObject(observer *o) { list<observer*>::iterator ite = find(_ob.begin(),_ob.end(),o); if(ite != _ob.end()) _ob.erase(ite); } void notifyObserver(string str) { list<observer*>::iterator ite; for(ite = _ob.begin(); ite!=_ob.end(); ite++) { if((*ite)->getName()==str) (*ite)->update(); } } void setTemp(int n) { temperature = n; notifyObserver("temperature"); } void setHumid(int n) { humid = n; notifyObserver("humid"); } int getTemp() { return temperature; } int getHumid() { return humid; } private: int temperature; int humid; }; class temperatureObserver:public observer { public: temperatureObserver(weather *sub, string s):observer(s) { m_sub = sub; name = "temperature"; } void update() { cout<<"now the temprature of "<<n<<" is "; cout<<m_sub->getTemp()<<endl; } }; class humidObserver:public observer { public: humidObserver(weather *sub, string s):observer(s) { m_sub = sub; name = "humid"; } void update() { cout<<"now the humid of "<<n<<" is "; cout<<m_sub->getHumid()<<endl; } }; int main() { weather *sub = new weather(); sub->registeObserver(new temperatureObserver(sub, "first tempratureObserver")); sub->registeObserver(new humidObserver(sub, "first humidObserver")); sub->registeObserver(new temperatureObserver(sub, "second tempratureObserver")); sub->registeObserver(new humidObserver(sub, "second humidObserver")); sub->registeObserver(new temperatureObserver(sub, "third tempratureObserver")); cout<<"change humid"<<endl; sub->setHumid(10); cout<<endl; cout<<"change temperature"<<endl; sub->setTemp(23); cout<<endl; cout<<"change humid"<<endl; sub->setHumid(45); cout<<endl; cout<<"change temperature"<<endl; sub->setTemp(80); cout<<endl; return 0; }
参考:http://www.cnblogs.com/fengye-dream/archive/2012/03/08/2385011.html
运行结果:

11.相关模式
mediator
通过封装复杂的更新语意,changeManager充当目标和观察者之间的中介者
singleton
changeManager可以用单件模式来保证这是唯一的一个
2012-05-21 23:08:05
浙公网安备 33010602011771号