设计模式学习(十七) 观察者模式 Observer

1.观察者模式的定义

工作让人头昏眼花

 对于观察者模式,官方的定义是“用于定义对象间一种一对多的依赖关系,使得每一个对象改变状态,则所有依赖于他们的对象都会得到通知。”,说穿了,就是对于对象的状态监控,将对象的状态改变变为信号,通过这个状态改变的信号,用于做别的事情。

 而观察者模式,这个名字其实理解性不是很高,他还有另一个名字—发布/订阅模式(publish/subscribe)。这样就更便于理解了,观察者观察被观察者,每当被观察者发生状态改变,则会传递改变的信息到观察者(至于只是改变的信号,还是附带所改变的信息,根据实际情况而定),观察者得到信息后,记录被观察者改变的信息。对比到发布/订阅模式,就是观察者订阅了被观察者,每当被观察者有新的动向时,就会将变化发布给观察者,观察者继续加以处理或记录等操作。

2.观察者模式的类图

观察者模式的类图
 通过观察者模式的可以看到,这不是一个只面向抽象类的设计模式,在实例类ConreteObserver中,其拥有ConcreteSubject的成员。而在使用时,主要也是通过ConreteObserver实例观察类中实现后续的操作。
同时信息的传递函数Notify和更新函数Update都是无参的,代表着两者其实传递的是一个信号,得到该信号后ConcreteObserver类应该直接在其成员变量Subject类中读取相应的信息。
 类图中的各个元素介绍如下:

  1. Subject抽象类:这是被观察者类的抽象类,通常,其内部会定义一个成员变量/列表来存储其观察者的信息。其主要用于定义接口,比如增删观察者,传递信息等接口。;
  2. Observer抽象类:其为观察者类的抽象类,其用于定义接口,其中最为主要的就是Updata接口的声明,所有的观察者都必须要有Updata自己信息的函数;
  3. ConcreteSubject实例类:其继承自Subject抽象类,在实现已经声明的固有接口后,根据其实际情况可增加自己的成员变量与函数。
  4. 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

方寸间沧海桑田

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值