观察者模式:
是讲有一个目标,众多个观察者去“观察”目标。目标是目标抽象类的一个派生类,观察者是观察者抽象类的一个派生类。当目标类的数据改变,所有对应的观察者对应去更新自己的状态。注意观察者处于被动地位,被观察者处理主动地位。
应用场景
比如有一个世界时钟程序,有多个图形时钟去显示比如北京时区,巴黎时区,等等。如果设置一个北京时间,那么其他时钟图形都需要更新(加上或者减去时差值)。典型的图形界面设计随处可见,一个温度程序,在温度湿度等条件改变时,要更新多种显示图形来呈现。
UML图示
原本是子类间进行耦合,把子类间的耦合提升到父类中去,这样父类中一次耦合关系,使得众子类耦合关系得到了解耦。从uml 也可以看的出来,父类间是紧耦合的,而子类中却是松耦合的。
举例
以改变北京时间,而其它时间也会随之而改变为例 ,程序如下:
#include <iostream>
#include <list>
#include <algorithm>
using namespace std;
class Subject;
class Observer //观察者
{
public:
virtual void update(Subject * subject) = 0;
int _hour;
int _min;
int _sec;
Subject * _subject;
};
class Subject //被观察者
{
public:
void addRegister(Observer * observer) // 观察者注册
{
observerList.push_back(observer);
}
void delRegister(Observer * observer) // 观察者取消
{
observerList.erase(find(observerList.begin(),observerList.end(),observer));
}
void notify()
{
list<Observer*>::iterator itr;
for(itr = observerList.begin(); itr != observerList.end(); ++itr)
{
(*itr)->update(this);
}
}
int _hour;
int _min;
int _sec;
list<Observer*> observerList; //注册后的观察者集合
};
class ChinaClock:public Subject //被观察者子类 北京时间
{
public:
void set(int hour, int min, int sec)
{
cout<<"China clock is set"<<endl;
_hour = hour;
_min = min;
_sec = sec;
notify(); //被观察者发出通知
}
};
class AmericaClock:public Observer //观察者子类 美国时间
{
public:
AmericaClock(Subject * subject)
{
_subject = subject;
_subject->addRegister(this);
}
void update(Subject * subject)
{
_hour = subject->_hour;
_min = subject->_min;
_sec = subject->_sec;
dis();
}
void dis()
{
cout<<"America clock is set"<<endl;
cout<<"hour:"<<_hour<<"min:"<<_min<<"sec:"<<_sec<<endl;
}
};
class LondenClock:public Observer //观察者子类 英国时间
{
public:
LondenClock(Subject * subject)
{
_subject = subject;
_subject->addRegister(this);
}
void update(Subject * subject)
{
_hour = subject->_hour;
_min = subject->_min;
_sec = subject->_sec;
dis();
}
void dis()
{
cout<<"Londen clock is set"<<endl;
cout<<"hour:"<<_hour<<"min:"<<_min<<"sec:"<<_sec<<endl;
}
};
class JapanClock:public Observer //观察者子类 日本时间
{
public:
JapanClock(Subject * subject)
{
_subject = subject;
_subject->addRegister(this);
}
void update(Subject * subject)
{
_hour = subject->_hour;
_min = subject->_min;
_sec = subject->_sec;
dis();
}
void dis()
{
cout<<"Japan clock is set"<<endl;
cout<<"hour:"<<_hour<<"min:"<<_min<<"sec:"<<_sec<<endl;
}
};
int main()
{
ChinaClock *cc = new ChinaClock; //创建北京时间被观察对象
AmericaClock *ac = new AmericaClock(cc); //创建美国时间观察对象
LondenClock *lc = new LondenClock(cc); //创建英国时间观察对象
JapanClock *jc = new JapanClock(cc); //创建日本时间观察对象
cc->set(1,2,3); //改变被观察北京时间
cout<<"-------------"<<endl;
cc->delRegister(jc); //移除日本时间观察者
cc->set(6,7,8); //再次改变被观察者时间
return 0;
}