当前位置: 首页 > article >正文

设计模式之【观察者模式】

观察者模式:

应用于发布-订阅消息模型中,订阅者订阅一个主题后,当有新消息到达时,所有订阅者都会收到通知。

主要关注的是对象之间的通信。是一种对象之间的一对多关系,多个对象依赖于一个对象,当被依赖的那个对象的状态发生改变时,其他对象都能够接收到相应的通知。

举个例子:

就像我们去看报纸,不用去挨个挨家出版社去问报纸做好了没,而是打个电话向出版社订阅报纸,等到哪个出版社的报纸好了,就会通知你。

简单画个图方便理解:

当我的Observer这些订阅者去订阅同一个主题Subject时,也就是多个对象依赖同一个对象,当主题检测有消息发生后会通知我们的订阅者。

这里也有具体的实现代码如下:

#include<iostream>
#include<unordered_map>
#include<list>
using namespace std;

class Observer {//观察者抽象类
public:
	//处理消息的接口
	virtual void handler(int msgid) = 0;
};
class Observer1 :public Observer {
public:
	void handler(int msgid) {
		switch (msgid) {
		case 1:
			cout << "Observer1 recv 1 msg!" << endl;
			break;
		case 2:
			cout << "Observer1 recv 2 msg!" << endl;
			break;
		default:
			cout << "Observer1 recv unkown msg!" << endl;
			break;
		}
	}
};
class Observer2 :public Observer {
public:
	void handler(int msgid) {
		switch (msgid) {
		case 2:
			cout << "Observer2 recv 2 msg!" << endl;
			break;
		default:
			cout << "Observer2 recv unkown msg!" << endl;
			break;
		}
	}
};
class Observer3 :public Observer {
public:
	void handler(int msgid) {
		switch (msgid) {
		case 1:
			cout << "Observer3 recv 1 msg!" << endl;
			break;
		case 3:
			cout << "Observer3 recv 3 msg!" << endl;
			break;
		default:
			cout << "Observer3 recv unkown msg!" << endl;
			break;
		}
	}
};
//主题类
class Subject {
public:
	//给主题增加观察者对象
	void addObserver(Observer* o ,int msgid) {
		_subMap[msgid].push_back(o);
		
	}
	//主题检测发生改变,通知相应的观察者对象
	void dispatch(int msgid) {
		auto it = _subMap.find(msgid);
		if (it != _subMap.end()) {
			for (Observer* p : it->second) {
				p->handler(msgid);
			}
		}
	}
private:
	unordered_map<int, list<Observer*>> _subMap;
};
int main() {
	Subject sub;
	Observer* p1 = new Observer1();
	Observer* p2 = new Observer2();
	Observer* p3 = new Observer3();
    //订阅主题:每个观察者自己感兴趣的消息id
	sub.addObserver(p1, 1);
	sub.addObserver(p1, 2);
	sub.addObserver(p2, 2);
	sub.addObserver(p3, 1);
	sub.addObserver(p3, 3);
	int msgid = 0;
	for (;;) {
		cout << "输入消息id:"; cin >> msgid;
		if (msgid == -1) 
			break;
		sub.dispatch(msgid);
	}
	return 0;
}

最后的运行截图如下:

可以看到当有消息id为1发生时,主题会检测到消息发生,然后通知给我们的观察者去处理消息。

Redis作为跨服务器通信的消息队列

知道Redis缓存数据库的童鞋应该知道,作为一个key-value格式来缓存热点数据之外,还有一个功能就是作为消息队列,也就是一个观察者设计模式的形式。

每一个观察者都会订阅一个通道,如果通道上有对应的消息事件发生,就会通知感兴趣的观察者。


http://www.kler.cn/a/453823.html

相关文章:

  • vulnhub靶场-matrix-breakout-2-morpheus攻略(截止至获取shell)
  • 【WebAR-图像跟踪】在Unity中基于Imagine WebAR实现AR图像识别
  • HUB、交换机、路由器和串口服务器
  • 广州大彩串口屏安卓/linux触摸屏四路CVBS输入实现同时显示!
  • taro中实现带有途径点的路径规划
  • 使用Webpack构建微前端应用
  • Java前端基础——CSS
  • 靶机系列|VULNHUB|DC-1
  • Vue.js组件开发-使用vue-pdf显示PDF
  • RK3568平台开发系列讲解(中断及异常篇)Linux 中断系统中的重要数据结构
  • v语言介绍
  • deepin 安装 kafka
  • 传统网络架构与SDN架构对比
  • Qt笔记:网络编程UDP
  • 智慧交通-Android车牌识别接口-车牌识别系统
  • 【提审】Android包提审报权限问题
  • excel技巧:excel文件怎么加密防止泄密?加密Excel文件的四种方法
  • 微机接口课设——基于Proteus和8086的打地鼠设计(8255、8253、8259)Proteus中Unknown 1-byte opcode / Unknown 2-byte opcode错误
  • 【Compose multiplatform教程09】【组件】Image组件
  • Effective C++ 条款 04:确定对象被使用前已先被初始化