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

【设计模式】观察者模式

观察者模式

        观察者模式也叫做观察者-监听者模式(发布-订阅模式):主要关注的是对象之间的通信,关注的是对象的一对多的关系,也就是多个对象都依赖一个对象,当该对象的状态发生改变时,其他对象都能接收到相应的通知。

例子:基于同一组数据,生成了很多不同的界面来显示,有曲线图显示方式,有圆饼图显示方式,有柱状图显示方式等等…,当底层数据发生改变时,所有基于同一组数据的图像显示都需要修改图像,那么此时有两种实现方式:

        1 .所有图形界面模块都去观察底层数据是否做了改变,如果变化,那么读取数据,修改图像显示。

        2.此时有一个类似Observer观察者的模块,专门用来观察数据的变化,对某组数据感兴趣的图形界面模块,事先可以向Observer观察者注册,它对哪些数据的变化感兴趣,那么当Observer观察者观测到数据真的发生变化,它会及时的通知对这组数据变化感兴趣的图形界面模块执行相应的代码操作。

简述MVC模式 

        因为在学习的过程中,很多人不知怎的,将观察者模式和MVC混为一谈。MVC模式最开始出现在WEB开发中,该模式能够很好的做到软件模块的高内聚,低耦合,所以其思想逐渐在各个软件开发领域都有涉及并且引用,MVC模式并不是OOP面向对象的设计模式,它是一种软件整体的架构思想。

M:指的是Model,数据模型层,表示系统底层的数据操作模块
V:指的是View,视图显示层,表示系统对于数据的展示模块
C:指的是Controller,控制层,表示监听用户事件交互,分发处理事件模块

        一般来说,MVC模式就是通过Controller控制层监听用户的请求事件,通过访问Model数据层,对数据进行相应的增删改查操作,然后找到合适的View视图用相应的数据进行渲染生成最终的显示视图(可以是图形界面,html web页面,json,protobuff等等),然后再把视图返回给用户。

        上图中,简单的罗列了观察者模式的类设计关系,Listener是对某些事件感兴趣的监听者,Listener1和Listener2是监听者具体的实现类,Observer是观察者,负责具体的事件观察并通知监听者处理已发生的事件。        

#include <iostream>
#include <string>
#include <unordered_map>
#include <list>// 观察者抽象类
class Observer
{
public:// 处理消息的接口virtual void handle(int msgid) = 0;
};
// 第一个观察者实例
class Observer1 : public Observer
{
public:void handle(int msgid){switch (msgid){case 1:std::cout << "Observer1 recv 1 msg !" << std::endl;break;case 2:std::cout << "Observer1 recv 2 msg !" << std::endl;break;default:std::cout << "Observer1 recv unknow msg !" << std::endl;break;}}
};
// 第二个观察者实例
class Observer2 : public Observer
{
public:void handle(int msgid){switch (msgid){case 2:std::cout << "Observer2 recv 2 msg !" << std::endl;break;default:std::cout << "Observer1 recv unknow msg !" << std::endl;break;}}
};
// 第三个观察者实例
class Observer3 : public Observer
{
public:void handle(int msgid){switch (msgid){case 1:std::cout << "Observer3 recv 1 msg !" << std::endl;break;case 3:std::cout << "Observer3 recv 3 msg !" << std::endl;break;default:std::cout << "Observer1 recv unknow msg !" << std::endl;break;}}
};
// 主题类
class Subject
{
public:// 给主题增加观察者对象void addObserver(Observer *obser, int msgid){_submap[msgid].push_back(obser);/*auto it = _submap.find(msgid);if (it != _submap.end()){it->second.push_back(obser);}else{std::list<Observer*> list;_submap.insert({ msgid, list });}*/}// 主题监测发生改变,通知相应的观察者对象处理事件void dispatch(int msgid){auto it = _submap.find(msgid);if (it != _submap.end()){for (Observer* pobser : it->second){pobser->handle(msgid);}}}
private:std::unordered_map<int, std::list<Observer*>> _submap;
};
int main()
{Subject subject;Observer* p1 = new Observer1();Observer* p2 = new Observer2();Observer* p3 = new Observer3();subject.addObserver(p1, 1);subject.addObserver(p1, 2);subject.addObserver(p2, 2);subject.addObserver(p3, 1);subject.addObserver(p3, 3);int msgid = 0;for (;;){std::cout << "输入消息id:";std::cin >> msgid;if (msgid == -1){break;}subject.dispatch(msgid);}return 0;
}

         上述的代码,实现了一个简单的观察者模式,输入消息id,如果有对这个msgid感兴趣的对象,就会被通知到,进而它可以去处理事物,以下是运行结果:


http://www.mrgr.cn/news/69135.html

相关文章:

  • 一.Spring cloud--Consul服务注册与发现(2)
  • 【测试框架篇】单元测试框架pytest(2):用例编写
  • 北京大学c++程序设计听课笔记101
  • 实现3D热力图
  • 使用python-Spark使用的场景案例具体代码分析
  • Git学习教程(更新中)
  • 嘉吉连续第七年亮相进博会
  • mp3格式音频怎么做成二维码?扫码获取音频文件的制作方法
  • PySR:高性能Python与Julia符号回归工具
  • jdk-Lock类的翻译
  • 开放式耳机如何选择?五款千万不能错过的开放式耳机机型推荐
  • 劫持微信聊天记录并分析还原 —— 访问数据库并查看聊天记录(五)
  • 微信小程序weui安装实战:NPM包最佳实践指南,快速构建UI组件库
  • 【CSP】爆零的独特姿势
  • PNG图片批量压缩exe工具+功能纯净+不改变原始尺寸
  • 在使用element中的抽屉<el-drawer>页签<el-tabs/>组合时,echarts图表宽度显示异常问题
  • 分布式和并发模型的比较和讨论记录
  • [Linux] 进程等待 | 进程替换
  • Codeforces Round 984 (Div. 3)
  • ODOO学习笔记(3):Odoo和Django的区别是什么?
  • Docker的轻量级可视化工具Portainer
  • ssm077铁岭河医院医患管理系统+vue(论文+源码)_kaic
  • 特殊符号大全
  • 驱动开发系列27 - Linux Kernel 内核调试环境配置
  • 【softmax基础】如何使用什么时候使用
  • Python:scipy.signal.find_peaks 查找数据内的波峰波谷