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

news/2024/7/23 21:59:25 标签: 观察者模式

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

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

发布者:

添加订阅者,将所有的订阅者存储起来
删除订阅者,将其从订阅者列表中删除
将消息发送给订阅者(发通知)

下面举一个生动的例子:

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

NewAgency.h

#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,重写子类的虚函数。

#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()这个状态更新函数

#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函数:

#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;
   
}

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


http://www.niftyadmin.cn/n/5019412.html

相关文章

纷享销客入选中国信通院《高质量数字化转型产品及服务全景图》

近期&#xff0c;在中国信息通信研究院主办的“2023数字生态发展大会”暨中国信通院“铸基计划”年中上&#xff0c;重磅发布了《高质量数字化转型产品及服务全景图&#xff08;2023&#xff09;》&#xff0c;纷享销客凭借先进的技术能力和十余年客户业务场景应用理解&#xf…

asio中的锁

asio到底有没有锁 asio是有锁的&#xff0c;所以规避锁的写法还是值得研究的 windows中的锁 先来张截图&#xff1a; dispatch_mutex_主要是为了保护定时器队列和完成端口回调的队列。 保护定时器队列 保护完成端口回调的队列 在PostQueuedCompletionStatus失败时&#x…

Python的math.sqrt()和math.pow()的使用

一、求平方根&#xff08;即开方&#xff09;——math.sqrt(被开方数) >>> math.sqrt(8) 2.8284271247461903 >>> math.sqrt(64) 8.0 # 等同于使用 **0.5 &#xff08;乘方数的倒数&#xff09; >>> 8**0.5 2.8284271247461903 >>> 64…

Spring系列文章:Bean的获取⽅式

一、简介 Spring为Bean提供了多种实例化⽅式&#xff0c;通常包括4种⽅式。&#xff08;也就是说在Spring中为Bean对象的创建准 备了多种⽅案&#xff0c;⽬的是&#xff1a;更加灵活&#xff09; 第⼀种&#xff1a;通过构造⽅法实例化 第⼆种&#xff1a;通过简单⼯⼚模式…

Pytorch 多卡并行(1)—— 原理简介和 DDP 并行实践

近年来&#xff0c;深度学习模型的规模越来越大&#xff0c;需要处理的数据也越来越多&#xff0c;单卡训练的显存空间和计算效率都越来越难以满足需求。因此&#xff0c;多卡并行训练成为了一个必要的解决方案本文主要介绍使用 Pytorch 的 DistributedDataParallel&#xff08…

Prometheus-PushGateway自定义监控项

文章目录 一、前言二、PushGateway安装三、PushGateway的使用四、PushGateway脚本思路 一、前言 pushgateway相比较exporter是主动向服务器发送请求&#xff0c;pushgateway本身也是一个程序&#xff0c;可以运行在任意节点上(不是必须在被监控端)&#xff0c;运行本身没有抓取…

【数据结构】红黑树的插入与验证

文章目录 一、基本概念1.时代背景2. 基本概念3.基本性质 二、实现原理1. 插入1.1变色1.2旋转变色①左旋②右旋③右左双旋④左右双旋 2.验证 源码总结 一、基本概念 1.时代背景 1972年鲁道夫拜尔(Rudolf Bayer)发明了一种数据结构&#xff0c;这是一种特殊的B树4阶情况。这些树…

go初识iris框架(四) -框架设置操作

前言 iris(1) iris(2) iris(3) 框架设置操作 当我们的一个路径是xxx/user/info,xxx/user/login,xxx/user/register的时候,我们发现前面都有一个user,我们如果用/{data:string}这样的话这样导致我们的路径是灵活的&#xff0c;所以我们得用其他方法 这里我们的路径是以anime为…