(一)觀察者模式-C++實現


觀察者模式:

    定義對象間的一種一對多的依賴關系,當一個對象的狀態發生變化時,所有依賴它的對象都得到通知並被自動更新。

它有四種角色:

主題(Subject):一個接口,規定了具體主題需要實現的方法。

觀察者(Observer):也是一個接口,規定了具體觀察者用來更新數據的方法。

具體主題:實現主題接口的一個實例,比如本例中的“就業通知中心”;里面會維護一個具體觀察者的集合。本文使用STL中的list。

具體觀察者:實現觀察者的一個實例,會包含存放主題的引用或者指針。

使用C++實現如下:

包含5個文件,頭文件兩個:主題類(Subject.h)觀察者類(Observer.h)

源文件兩個:主題類(Subject.cpp)觀察者類(Observer.h)

一個測試文件。

//Subject.h

#ifndef _SUBJECT_H_
#define _SUBJECT_H_
#include "Observer.h"
#include <list>
#include <string>
using namespace std;
class Observer;//注意C++中雖然包含了頭文件這里也需要聲明
typedef list<Observer*> myList;

class Subject{
public:
	Subject(){}
	virtual ~Subject(){}
	virtual void addObserver(Observer* o) = 0;
	virtual void deleteObserver(Observer* o) = 0;
	virtual void notifyObservers() = 0;

};

class SeekJobCenter : public Subject
{
public:
	SeekJobCenter();
	~SeekJobCenter(){}
	void addObserver(Observer* o);
	void deleteObserver(Observer* o);

	void notifyObservers();
	void giveNewMessage(string str);

private:
	string mess;
	bool changed;
	myList personList;

};


#endif

//Subject.cpp

//具體的主題
#include "stdafx.h"
#include "Subject.h"
#include "Observer.h"
#include <list>

SeekJobCenter::SeekJobCenter()
{
	mess = "";
	changed = false;
}
void SeekJobCenter::addObserver(Observer* o)
{
	list<Observer*>::iterator it;
	//判斷原始維護的list中是否存在添加的對象
	it = find(personList.begin(), personList.end(), o);
	if (it == personList.end())//不存在
	{
		personList.push_back(o);
	}
	return;
}

void SeekJobCenter::deleteObserver(Observer* o)
{
	list<Observer*>::iterator it;
	it = find(personList.begin(), personList.end(), o);
	if (it != personList.end())//存在
	{
		personList.remove(*it);
		delete(*it);
	}
	return;
}

void SeekJobCenter::notifyObservers()
{
	list<Observer*>::iterator it;
	if (changed)
	{
		for (it = personList.begin(); it != personList.end(); ++it)
		{
			(*it)->hearTelephone(mess);
		}
		changed = false;
	}
	return;
}

void SeekJobCenter::giveNewMessage(string str)
{
	if (0 == strcmp(str.c_str(), mess.c_str()))
	{
		changed = false;
	}
	else
	{
		mess = str;
		changed = true;
	}
	return;
}

//Observer.h

#ifndef _OBSERVER_H_
#define _OBSERVER_H_
#include <string>
#include <iostream>
#include <list>
#include "Subject.h"
using namespace std;
class Subject;
/*
觀察者基類
*/
class Observer
{
public:
	Observer(){};
	virtual ~Observer(){};
	virtual void hearTelephone(string heardMess) = 0;

};

class UniversityStudent : public Observer
{
public:
	UniversityStudent(Subject* subject);
	virtual ~UniversityStudent(){};
	void hearTelephone(string heardMess);

private:
	Subject* subject;

};

class HaiGui : public Observer
{
public:
	HaiGui(Subject *subject);
	virtual ~HaiGui(){};
	void hearTelephone(string heardMess);

private:
	Subject *subject;

};


#endif

//Observer.cpp

 1 #include "stdafx.h"
 2 #include "Observer.h"
 3 #include "Subject.h"
 4 
 5 UniversityStudent::UniversityStudent(Subject* subject)
 6 {
 7     if (NULL != subject)
 8     {
 9         this->subject = subject;
10     }
11     else
12     {
13         return;
14     }
15 
16     subject->addObserver(this);
17 }
18 void UniversityStudent::hearTelephone(string heardMess)
19 {
20     std::cout << "I am a university student" << std::endl;
21     std::cout << "I hear message is " << heardMess << std::endl;
22     return;
23 }
24 
25 HaiGui::HaiGui(Subject* subject)
26 {
27     if (NULL != subject)
28     {
29         this->subject = subject;
30     }
31     else
32     {
33         return;
34     }
35     subject->addObserver(this);
36 }
37 
38 void HaiGui::hearTelephone(string heardMess)
39 {
40     std::cout << "I am a HaiGui" << std::endl;
41     std::cout << "I hear message is " ;
42     cout << heardMess << endl;
43     return;
44 }
View Code

 

 

最后一個測試的文件:

#include "stdafx.h"
#include "Observer.h"
#include "Subject.h"

int _tmain(int argc, _TCHAR* argv[])
{
	SeekJobCenter *center = new SeekJobCenter();
	UniversityStudent *chengchaolee = new UniversityStudent(center);
	HaiGui *haigui = new HaiGui(center);
	center->giveNewMessage("I need a cook");
	center->notifyObservers();
	center->giveNewMessage("I need a xxxx");
	center->notifyObservers();

	delete center;
	delete chengchaolee;
	delete haigui;
	return 0;
}

    定義兩個具體的觀察者,並且以具體主題作為參數,代表它觀察的對象,然后當主題推送數據時,觀察者就會收到消息,即“推數據”的方式,當然還有一種觀察者模式采用的是拉數據,即由觀察者自己定義需要什么數據,主題在notify的時候並不傳遞參數而是在觀察者更新數據時,將Subject向下轉換為具體Subject,從而獲取其中相應的數據,這種方式叫做“拉數據”。

    值得注意的是,C++在實現的時候,采用list存儲具體觀察者,需要使用list<Observer*>類型,即使用指針。不然會編譯不通過,因為Observer是虛基類,無法實例化。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM