观察者 模式是行为模式之一,它的作用是当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对象状态。
观察者模式提供给关联对象一种同步通信的手段,使某个对象与依赖它的其他对象之间保持状态同步。
Subject(被观察者)
被观察的对象。当需要被观察的状态发生变化时,需要通知队列中所有观察者对象。Subject需要维持(添加,删除,通知)一个观察者对象的队列列表。
ConcreteSubject
被观察者的具体实现。包含一些基本的属性状态及其他操作。
Observer(观察者)
接口或抽象类。当Subject的状态发生变化时,Observer对象将通过一个callback函数得到通知。
ConcreteObserver
观察者的具体实现。得到通知后将完成一些具体的业务逻辑处理。
具体实例
#include <iostream>
#include <vector>
using namespace std;
//观察者基类
class Observe
{
public:
Observe(int tag)
{
m_tag = tag;
}
virtual void update(){}
public:
//用来标记每个注册的观察者
int m_tag;
//保存主题者发来的消息
string m_news;
};
class Teacher : public Observe
{
public:
Teacher(int tag) : Observe(tag)
{
}
void update()
{
cout << "老师收到:" << m_news.c_str()<<endl;
}
};
class Student : public Observe
{
public:
Student(int tag) : Observe(tag)
{
}
void update()
{
cout << "学生收到:" << m_news.c_str()<<endl;
}
};
class Parent : public Observe
{
public:
Parent(int tag) : Observe(tag)
{
}
void update()
{
cout << "家长收到:" << m_news.c_str()<<endl;
}
};
主题者(消息发布者)
//主题者基类
class School
{
public:
//观察者向主题者注册
void registObserve(Observe *observe)
{
if (observe == NULL)
return;
observes.push_back(observe);
}
//观察者从主题者移除
void removeObserve(Observe &observe)
{
for (it = observes.begin(); it != observes.end(); it++)
{
//根据观察者的标志移除观察者
if ((*it)->m_tag == observe.m_tag)
{
observes.erase(it);
break;
}
}
}
void notifyObserve()
{
for (it = observes.begin(); it != observes.end(); it++)
{
(*it)->m_news = m_news;
(*it)->update();
}
}
void setSubjectChange(string news)
{
m_news = news;
notifyObserve();
}
private:
vector<Observe *>observes;
vector<Observe *>::iterator it;
string m_news;
};
其中主题者基类可以设计成抽象类,只负责对观察者进行注册,移除,更新等操作,而发布的具体内容则可以由主题者的功能进行重写。
main函数实现
//主题者
School *s = new School;
//初始化观察者子类
Observe *teacher = new Teacher(1);
Observe *student = new Student(2);
Observe *parent = new Parent(3);
//向主题者注册观察者
s->registObserve(teacher);
s->registObserve(student);
s->registObserve(parent);
s->setSubjectChange("来自主题者的消息");
运行结果如下:
可以看到,当主题者内容发生改变时,观察者都接收到了消息,
继续删除家长这个观察者。
//家长不想收到主题者的消息
cout << endl << endl;
s->removeObserve(*parent);
s->setSubjectChange("家长已经被我踢出去了");
运行结果:
删除家长之后,主题者发布新消息家长就收不到了
main函数完整代码如下:
int main(int argc, char *args[])
{
//主题者
School *s = new School;
//初始化观察者子类
Observe *teacher = new Teacher(1);
Observe *student = new Student(2);
Observe *parent = new Parent(3);
//向主题者注册观察者
s->registObserve(teacher);
s->registObserve(student);
s->registObserve(parent);
s->setSubjectChange("来自主题者的消息");
//家长不想收到主题者的消息
cout << endl << endl;
s->removeObserve(*parent);
s->setSubjectChange("家长已经被我踢出去了");
getchar();
return 0;
}
每天进步一点点,终究会成为大神