观察者模式是大学阶段应该掌握的几种重要的模式之一,它的用处广泛,而且其变种更能解决许多实际问题。下面详细的介绍一下。
名称:观察者模式--Observer
别名:Dependents, Publish-Subscribe
意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
下面用一个教师-学生的例子说明观察者模式,其中学生是观察者,教师是被观察者,不过这个也适用于电器-开关的例子,可以把电器看作观察者,开关看作被观察者,当开关开始有动作的时候,观察者接收到信息:
//-------------------------------------------------------------------
// Subject.h 被观察对象
//-------------------------------------------------------------------
#ifndef SUBJECT_H
#define SUBJECT_H
#include "Observer.h"
class Observer;
class Subject
{
public:
virtual ~Subject(){}
virtual void Attach(Observer *aObserver) = 0;
virtual void Talk() = 0;
virtual char *GetContent() const = 0;
virtual void SetContent(char *aContent) = 0;
protected:
Subject(){};
};
#endif
//--------------------------------------------------------------------------
// Teacher.h
//--------------------------------------------------------------------------
#ifndef TEACHER_H
#define TEACHER_H
#include "Subject.h"
#include <list>
#include <iterator>
class Teacher : public Subject
{
public:
Teacher();
virtual void Attach(Observer *aObserver);
virtual void Talk();
virtual char *GetContent() const;
virtual void SetContent(char *aContent);
private:
std::list<Observer *> observerList;
char *content;
};
#endif;
//---------------------------------------------------------------------
// Teacher.cpp
//---------------------------------------------------------------------
#include "Teacher.h"
Teacher::Teacher()
{
content = "现在开始上课";
}
void Teacher::Attach(Observer *aObserver)
{
observerList.push_back(aObserver);
}
void Teacher::SetContent(char *aContent)
{
content = aContent;
}
void Teacher::Talk()
{
std::list<Observer *>::iterator students;
for(students = observerList.begin() ; students != observerList.end() ; ++students)
{
((Observer *)(*students))->Listen(this);
}
}
char *Teacher::GetContent() const
{
return content;
}
//--------------------------------------------------------------------------------
// Observer.h 观察者
//--------------------------------------------------------------------------------
#ifndef OBSERVER_H
#define OBSERVER_H
#include "Subject.h"
class Subject;
class Observer
{
public:
virtual void Listen(Subject *aSubject) = 0;
virtual ~Observer(){}
protected:
Observer(){};
};
#endif
//------------------------------------------------------------------------
// Student.h
//------------------------------------------------------------------------
#ifndef STUDENT_H
#define STUDENT_H
#include "Observer.h"
class Student : public Observer
{
public:
Student(char* = "学生");
char *GetName() const;
virtual void Listen(Subject *aSubject);
private:
char *name;
};
#endif
//----------------------------------------------------------------
// Student.cpp
//----------------------------------------------------------------
#include <iostream>
#include "Student.h"
Student::Student(char *aName)
{
name = aName;
}
void Student::Listen(Subject *aSubject)
{
std::cout << GetName() << ":老师刚才说," << aSubject->GetContent() << std::endl;
}
char *Student::GetName() const
{
return name;
}
//-------------------------------------------------------------
// demo.cpp
//-------------------------------------------------------------
#include "Student.h"
#include "Teacher.h"
int main()
{
Student *student1 = new Student("张三");
Student *student2 = new Student("李四");
Student *student3 = new Student("王五");
Teacher teacher;
teacher.Attach(student1);
teacher.Attach(student2);
teacher.Attach(student3);
teacher.Talk();
teacher.SetContent("今天我们一起来学习C++");
teacher.Talk();
std::system("PAUSE");
return 0;
}
OGRE里面观察者模式应用得很多,比如FrameListener就是一个观察者,观测每一帧的开始、结束。如:
virtual bool frameStarted(const FrameEvent& evt)
{ (void)evt; return true; }
用户需要处理自己的事件时只需继承该FrameListener并重写frameStarted、end等,FrameEvent事件包含了各种所需信息。