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

目录

1.意图

2.UML类图

3.GOF角色说明  

4.代码实现一

5.代码实现二


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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值