您的位置:首页 > 其它

设计模式(15) - Observer观察者模式

2013-12-22 00:11 429 查看

1. 意图

观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。

2. UML类图



主题(subject)和观察者(observers)之间定义为了一对多的关系。多个观察者依赖于某个主题,这样当主题的状态发生改变时,观察者就会被通知到。得到通知后,观察者就能使用新的值进行更新。

3. 代码实现

例子1: 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

例子2

与上一个例子不同之处在于,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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: