【设计模式】观察者模式
观察者模式
观察者模式也叫做观察者-监听者模式(发布-订阅模式):主要关注的是对象之间的通信,关注的是对象的一对多的关系,也就是多个对象都依赖一个对象,当该对象的状态发生改变时,其他对象都能接收到相应的通知。
例子:基于同一组数据,生成了很多不同的界面来显示,有曲线图显示方式,有圆饼图显示方式,有柱状图显示方式等等…,当底层数据发生改变时,所有基于同一组数据的图像显示都需要修改图像,那么此时有两种实现方式:
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感兴趣的对象,就会被通知到,进而它可以去处理事物,以下是运行结果: