(一)观察者模式-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 }
最后一个测试的文件:
#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是虚基类,无法实例化。