【C++基础】观察者模式(“发布-订阅”模式)

本文参考:观察者模式 - 摩根斯 | 爱编程的大丙

观察者模式允许我们定义一种订阅机制,可在对象事件发生时通知所有的观察者对象,使它们能够自动更新。观察者模式还有另外一个名字叫做"发布-订阅"模式。

发布者:

添加订阅者,将所有的订阅者存储起来

删除订阅者,将其从订阅者列表中删除

将消息发送给订阅者(发通知)

下面举一个生动的例子:

NewsAgency是一个抽象类,表示发布者,其派生类为 Morgans和Gossip,代表不同的两个报社

NewAgency.h

cpp 复制代码
#pragma once
#include <string>
#include <list>

using namespace std;

//声明订阅者类
class Observer;

class NewsAgency
{
public:
	void attach(Observer* ob);  //添加订阅者
	void deatch(Observer* ob);  //删除订阅者
	virtual void notify(string msg) = 0;  //通知list中的所有订阅者
	virtual ~NewsAgency() {};   //析构

protected:
	list<Observer*> m_list;   //存储订阅者对象
};


class Morgans :public NewsAgency
{
public:
	void notify(string msg) override;
};

class Gossip :public NewsAgency
{
public:
	void notify(string msg) override;
};

在NewsAgency.cpp,重写子类的虚函数。

cpp 复制代码
#include "NewsAgency.h"
#include "Observer.h"
#include <iostream>


void NewsAgency::attach(Observer* ob)
{
	m_list.push_back(ob);
}

void NewsAgency::deatch(Observer* ob)
{
	m_list.remove(ob);
}


void Morgans::notify(string msg)
{
	cout << "摩根斯新闻社报纸的订阅者一共有" << m_list.size()  << endl;
	for (const auto& item : m_list)
	{
		item->update(msg);	// 订阅者类的定义在下面
	}
}


void Gossip::notify(string msg)
{
	cout << "八卦新闻社报纸的订阅者一共有 " << m_list.size() << endl;
	for (const auto& item : m_list)
	{
		item->update(msg);
	}


}

订阅者(也可称为观察者):

Observer.h

首先给所有的观察者定义一个抽象的基类。

然后子类在各自的类中分别重写了update()这个状态更新函数

cpp 复制代码
#pragma once
#include <string>
#include <iostream>
#include "NewsAgency.h"

//抽象的订阅者类
class Observer
{
public:
	//需要通过构造函数给观察者类提供一个信息的发布者
	//通过发布者对象将观察者对象存储了起来,这样就可以收到发布者推送的消息了。
	Observer(string name, NewsAgency* news)
		:m_name(name), m_news(news)
	{
		m_news->attach(this);
	}
	//观察者取消订阅,取消之后将不再接收订阅消息。
	void unsubscribe()
	{
		m_news->deatch(this);
	}
	//观察者得到最新消息之后,用于更新自己当前的状态。
	virtual void update(string msg) = 0;
	virtual ~Observer() {};

protected:
	string m_name;
	NewsAgency* m_news;
};


class Dragon :public Observer
{
public:
	using Observer::Observer;
	void update(string msg) override
	{
		cout<< "路飞的老爸革命军龙收到消息: " << msg << endl;
	}
};


class Shanks : public Observer
{
public:
	using Observer::Observer;
	void update(string msg) override
	{
		cout << "路飞的引路人红发香克斯收到消息: " << msg << endl;
	}
};

class Bartolomeo : public Observer
{
public:
	using Observer::Observer;
	void update(string msg) override
	{
		cout << "路飞的头号粉丝巴托洛米奥收到消息: " << msg << endl;
	}
};

main函数:

cpp 复制代码
#include <iostream>
#include "NewsAgency.h"
#include "Observer.h"

using namespace std;


int main()
{
	Morgans* ms = new Morgans;
	Gossip* gossip = new Gossip;
	Dragon* dragon = new Dragon("蒙奇·D·龙", ms);
	Shanks* shanks = new Shanks("香克斯", ms);
	Bartolomeo* barto = new Bartolomeo("巴托洛米奥", gossip);

	ms->notify("蒙奇·D·路飞成为新世界的新的四皇之一, 赏金30亿贝里!!!");

	cout << "======================================" << endl;
	gossip->notify("女帝汉库克想要嫁给路飞, 给路飞生猴子, 哈哈哈...");

	delete ms;
	delete gossip;
	delete dragon;
	delete shanks;
	delete barto;
   
}

最后总结一下观察者模式的应用场景:

当一个对象的状态发生变化,并且需要改变其它对象的时候;或者当应用中一些对象必须观察其它对象的时候可以使用观察者模式。

相关推荐
小白不太白95012 小时前
设计模式之 观察者模式
观察者模式·设计模式
蓝田~14 小时前
观察者模式和订阅模式
windows·观察者模式
Mr. zhihao4 天前
从业务场景学习观察者模式
学习·观察者模式
Mr. zhihao5 天前
观察者模式 vs 不使用观察者模式:商品库存变化的通知
java·观察者模式
zgy111122210 天前
高阶函数全解析(定义、应用 -- 函数柯理化 反柯理化 发布订阅模式 观察者模式)
观察者模式
杨充10 天前
13.观察者模式设计思想
java·redis·观察者模式
G皮T10 天前
【设计模式】行为型模式(一):模板方法模式、观察者模式
java·观察者模式·设计模式·模板方法模式·template method·行为型模式·observer
小牛itbull11 天前
JavaScript 观察者设计模式
开发语言·javascript·观察者模式
孤邑12 天前
【设计模式】观察者模式
c++·笔记·学习·观察者模式·设计模式
霁月风15 天前
设计模式——观察者模式
c++·观察者模式·设计模式