目录
1.意图
观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。
2.UML类图
3.GOF角色说明
Subject(目标)
--目标知道它的观察者。可以有任意多个观察者观察同一个目标。
--提供注册和删除观察者对象的接口。
Observer(观察者)
--为那些在目标发生改变时需要获得通知的对象,定义一个更新接口。
ConcreteSubject(具体目标)
--将有关状态存入各个ConcreteObserver对象。
--当它的状态发生改变时,向它的各个观察者发出通知。
ConcreteObserver(具体观察者)
--维护一个指向ConcreteSUbject对象的引用。
--存储有关状态,这些状态应与目标的状态保持一致。
--实现Observer的更新接口以使自身状态与目标的状态保持一致。
subject和observers之间定义为了一对多的关系。多个观察者依赖于某个目标,这样当目标的状态发生改变时,观察者就会被通知到。得到通知后,观察者就能使用新的值进行更新。
4.代码实现一
GoF版本:
#include<iostream>
#include<vector>
#include<algorithm>
#include<string.h>
#include<time.h>
using namespace std;
class Subject;
class Observer
{
public:
Observer() {}
~Observer() {}
virtual void Update(Subject *theChangeSubject) = 0;
};
class Subject
{
public:
Subject() {}
virtual ~Subject() {}
virtual void Attach(Observer *);
virtual void Detach(Observer *);
virtual void Notify();
private:
vector<Observer *> _observers;
};
void Subject::Attach(Observer *ob)
{
_observers.push_back(ob);
}
void Subject::Detach(Observer *ob)
{
vector<Observer*>::iterator pos = find(_observers.begin(), _observers.end(), ob);
if (pos != _observers.end())
_observers.erase(pos);
}
void Subject::Notify()
{
for_each(_observers.begin(), _observers.end(), [this](Observer *element) {
element->Update(this);
});
}
class ClockTimer :public Subject
{
public:
ClockTimer() { _strtime_s(tmpbuf); }
int GetHour();
int GetMinute();
int GetSecond();
void Tick();
private:
char tmpbuf[128];
};
//根据TZ环境变量来设置时区。如果TZ没有被设置,则查询操作系统
//来获取默认值
void ClockTimer::Tick()
{
_tzset();
//获取系统风格的时间
_strtime_s(tmpbuf);
Notify();
}
int ClockTimer::GetHour()
{
char timebuf[128];
strncpy_s(timebuf, tmpbuf, 2);
timebuf[2] = NULL;
return atoi(timebuf);
}
int ClockTimer::GetMinute()
{
char timebuf[128];
strncpy_s(timebuf, tmpbuf + 3, 2);
timebuf[2] = NULL;
return atoi(timebuf);
}
int ClockTimer::GetSecond()
{
char timebuf[128];
strncpy_s(timebuf, tmpbuf + 6, 2);
timebuf[2] = NULL;
return atoi(timebuf);
}
class DigitalClock :public Observer
{
public:
DigitalClock(ClockTimer *);
~DigitalClock();
void Update(Subject *);
void Draw();
private:
ClockTimer *_subject;
};
DigitalClock::DigitalClock(ClockTimer *s) : _subject(s)
{
_subject->Attach(this);
}
DigitalClock::~DigitalClock()
{
_subject->Detach(this);
}
void DigitalClock::Update(Subject *theChangedSubject)
{
int hour = _subject->GetHour();
int minute = _subject->GetMinute();
int sec = _subject->GetSecond();
cout << "Digital time is " << hour << ":" << minute << ":" << sec << endl;
}
class AnalogClock :public Observer
{
public:
AnalogClock(ClockTimer *);
~AnalogClock();
void Update(Subject *);
void Draw();
private:
ClockTimer *_subject;
};
AnalogClock::AnalogClock(ClockTimer *s) : _subject(s)
{
_subject->Attach(this);
}
AnalogClock::~AnalogClock()
{
_subject->Detach(this);
}
void AnalogClock::Update(Subject *theChangedSubject)
{
if (theChangedSubject == _subject)
Draw();
}
void AnalogClock::Draw()
{
int hour = _subject->GetHour();
int minute = _subject->GetMinute();
int sec = _subject->GetSecond();
cout << "Analog time is " << hour << ":" << minute << ":" << sec << endl;
}
int main()
{
ClockTimer timer;
DigitalClock dc(&timer);
AnalogClock ac(&timer);
timer.Tick();
return 0;
}
运行结果为:
Digital time is 20:9:14
Analog time is 20:9:14
5.代码实现二
与上一个例子不同之处在于,MySubject类与MyObserver类之间没有编译期间的依赖关系,而是在运行时动态创建的。
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
class Observer
{
public:
virtual ~Observer(){}
virtual void update(int message) = 0;
};
class Subject
{
public:
virtual ~Subject() {}
virtual void subscribe(Observer *);
virtual void unsubscribe(Observer *);
virtual void notify(int message);
private:
vector<Observer*> _obsvList;
};
void Subject::subscribe(Observer *ob)
{
_obsvList.push_back(ob);
}
void Subject::unsubscribe(Observer *ob)
{
vector<Observer*>::iterator pos = find(_obsvList.begin(), _obsvList.end(), ob);
if (pos != _obsvList.end())
_obsvList.erase(pos);
}
void Subject::notify(int message)
{
for_each(_obsvList.begin(), _obsvList.end(), [message](Observer* element) {
element->update(message);
});
}
class MySubject : public Subject
{
public:
enum message { ADD, REMOVE };
};
class MyObserver : public Observer
{
public:
explicit MyObserver(const string &str) :_name(str) {}
void update(int message) {
cout << _name << " got message: " << message << endl;
}
private:
string _name;
};
int main()
{
MyObserver obA("observerA");
MyObserver obB("observerB");
MyObserver obC("observerC");
MySubject sub;
sub.subscribe(&obA);
sub.subscribe(&obB);
sub.subscribe(&obC);
sub.subscribe(&obB);
sub.notify(MySubject::ADD);
sub.notify(MySubject::REMOVE);
getchar();
return 0;
}
运行结果为:
observerA got message: 0
observerB got message: 0
observerC got message: 0
observerB got message: 0
observerA got message: 1
observerB got message: 1
observerC got message: 1
observerB got message: 1