1.观察者模式的定义
工作让人头昏眼花
对于观察者模式,官方的定义是“用于定义对象间一种一对多的依赖关系,使得每一个对象改变状态,则所有依赖于他们的对象都会得到通知。”,说穿了,就是对于对象的状态监控,将对象的状态改变变为信号,通过这个状态改变的信号,用于做别的事情。
而观察者模式,这个名字其实理解性不是很高,他还有另一个名字—发布/订阅模式(publish/subscribe)。这样就更便于理解了,观察者观察被观察者,每当被观察者发生状态改变,则会传递改变的信息到观察者(至于只是改变的信号,还是附带所改变的信息,根据实际情况而定),观察者得到信息后,记录被观察者改变的信息。对比到发布/订阅模式,就是观察者订阅了被观察者,每当被观察者有新的动向时,就会将变化发布给观察者,观察者继续加以处理或记录等操作。
2.观察者模式的类图
通过观察者模式的可以看到,这不是一个只面向抽象类的设计模式,在实例类ConreteObserver中,其拥有ConcreteSubject的成员。而在使用时,主要也是通过ConreteObserver实例观察类中实现后续的操作。
同时信息的传递函数Notify和更新函数Update都是无参的,代表着两者其实传递的是一个信号,得到该信号后ConcreteObserver类应该直接在其成员变量Subject类中读取相应的信息。
类图中的各个元素介绍如下:
- Subject抽象类:这是被观察者类的抽象类,通常,其内部会定义一个成员变量/列表来存储其观察者的信息。其主要用于定义接口,比如增删观察者,传递信息等接口。;
- Observer抽象类:其为观察者类的抽象类,其用于定义接口,其中最为主要的就是Updata接口的声明,所有的观察者都必须要有Updata自己信息的函数;
- ConcreteSubject实例类:其继承自Subject抽象类,在实现已经声明的固有接口后,根据其实际情况可增加自己的成员变量与函数。
- ConcreteObserver实例类:其继承自Observer抽象类,在实现已经声明的固有接口后,根据其实际情况可增加自己的成员变量与函数。但其内部必须要有其所观察的观察者的成员变量(常为指针),通过调用该成员变量,获取所观察对象的内部数据的具体改变情况。
3.观察者模式的代码实现
本例的代码实现是参照Steins;Gate的世界观来写的,在该作中,冈部伦太郎作为世界线的唯一观测者而不断跳跃时空来改变过去/未来。由此,将世界World作为本例的Subject抽象类,而世界线WorldLine则作为本例的ConcreteSubject实例类。观测者类仍为Observer类,其中仅定义了接口Updata,世界线的观测者类WorldLine_Observer即为ConcreteObserver实例类,其内部存储了其所观测的世界线(是α还是β世界线),当世界线开始变动时,其内的Update函数将会被世界线的通知函数Notify所调用,然后观测者读取其内部成员变量(所储存的世界线)来得知当前的世界线是多少。
#include <iostream>
#include <string>
#include <list>
using namespace std;
class Observer
{
public:
virtual void Update() = 0;
};
class World
{
public:
World() { m_observerlist.clear(); }
virtual void Attach(Observer *observer) = 0;
virtual void Delete(Observer *observer) = 0;
virtual void Notify() = 0;
protected:
list<Observer*> m_observerlist;
};
class WorldLine : public World
{
public:
void Attach(Observer *observer) override { m_observerlist.push_back(observer); }
void Delete(Observer *observer) override { m_observerlist.remove(observer); }
void Notify() override
{
for (auto &s : m_observerlist)
s->Update();
}
WorldLine(string currentworldline) : m_worldline(currentworldline)
{
cout << "CurrentWorldLine is " << currentworldline << endl;
}
string getWorldLine() { return m_worldline; }
void setWorldLine(string worldline) { m_worldline = worldline; }
private:
string m_worldline;
};
class WorldLine_Observer : public Observer
{
public:
WorldLine_Observer(string name, WorldLine* world) : m_name(name), m_world(world) {};
void Update()
{
cout << m_name << " feel that! The WorldLine now change to " << m_world->getWorldLine() << endl;
}
private:
string m_name;
WorldLine* m_world;
};
int main()
{
WorldLine* alpha_worldline = new WorldLine("1.02412");
WorldLine* beta_worldline = new WorldLine("2.45672");
WorldLine_Observer* Makise_Kurisu = new WorldLine_Observer("Makise_Kurisu", alpha_worldline);
WorldLine_Observer* Okabe_Rintaro = new WorldLine_Observer("Okabe_Rintaro", beta_worldline);
alpha_worldline->Attach(Makise_Kurisu);
beta_worldline->Attach(Okabe_Rintaro);
alpha_worldline->setWorldLine("1.45321");
alpha_worldline->Notify();
beta_worldline->setWorldLine("2.86712");
beta_worldline->Notify();
delete alpha_worldline;
delete beta_worldline;
delete Makise_Kurisu;
delete Okabe_Rintaro;
return 0;
}