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

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

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

相关推荐
东风吹柳2 天前
观察者模式(sigslot in C++)
c++·观察者模式·信号槽·sigslot
T1an-13 天前
设计模式之【观察者模式】
观察者模式·设计模式
真想骂*6 天前
观察者模式:它究竟在观察什么?
java·开发语言·观察者模式
夏旭泽7 天前
设计模式-观察者模式
观察者模式·设计模式
澄澈i7 天前
设计模式学习[12]---观察者模式
学习·观察者模式·设计模式
问道飞鱼10 天前
【设计模式】观察者模式深度讲解
观察者模式·设计模式
吾与谁归in11 天前
【C#设计模式(20)——观察者模式(Observer Pattern)】
观察者模式·设计模式·c#
你又食言了哦18 天前
C++观察者模式Observer
开发语言·c++·观察者模式
ohMyGod_12318 天前
手写观察者模式
观察者模式
Theodore_102219 天前
14 设计模式值观察者模式(书籍发布通知案例)
java·开发语言·算法·观察者模式·设计模式·java-ee