观察者模式(Observer)和发布(Publish/订阅模式(Subscribe)的区别
观察者模式(Observer)和发布(Publish/订阅模式(Subscribe)的区别
在翻阅资料的时候,有人把观察者(Observer)模式等同于发布(Publish)/订阅(Subscribe)模式,也有人认为这两种模式还是存在差异,而我认为确实是存在差异的,本质上的区别是调度的地方不同。
观察者模式
比较概念的解释是,目标和观察者是基类,目标提供维护观察者的一系列方法,观察者提供更新接口。具体观察者和具体目标继承各自的基类,然后具体观察者把自己注册到具体目标里,在具体目标发生变化时候,调度观察者的更新方法。
比如有个“天气中心”的具体目标A,专门监听天气变化,而有个显示天气的界面的观察者B,B就把自己注册到A里,当A触发天气变化,就调度B的更新方法,并带上自己的上下文。
发布/订阅模式
比较概念的解释是,订阅者把自己想订阅的事件注册到调度中心,当该事件触发时候,发布者发布该事件到调度中心(顺带上下文),由调度中心统一调度订阅者注册到调度中心的处理代码。
比如有个界面是实时显示天气,它就订阅天气事件(注册到调度中心,包括处理程序),当天气变化时(定时获取数据),就作为发布者发布天气信息到调度中心,调度中心就调度订阅者的天气处理程序。
总结
1. 从两张图片可以看到,最大的区别是调度的地方。
虽然两种模式都存在订阅者和发布者(具体观察者可认为是订阅者、具体目标可认为是发布者),但是观察者模式是由具体目标调度的,而发布/订阅模式是统一由调度中心调的,所以观察者模式的订阅者与发布者之间是存在依赖的,而发布/订阅模式则不会。
2. 两种模式都可以用于松散耦合,改进代码管理和潜在的复用。
附录
观察者模式实现代码(JavaScript版):
- //观察者列表
- function ObserverList(){
- this.observerList = [];
- }
- ObserverList.prototype.add = function( obj ){
- return this.observerList.push( obj );
- };
- ObserverList.prototype.count = function(){
- return this.observerList.length;
- };
- ObserverList.prototype.get = function( index ){
- if( index > -1 && index < this.observerList.length ){
- return this.observerList[ index ];
- }
- };
- ObserverList.prototype.indexOf = function( obj, startIndex ){
- var i = startIndex;
- while( i < this.observerList.length ){
- if( this.observerList[i] === obj ){
- return i;
- }
- i++;
- }
- return -1;
- };
- ObserverList.prototype.removeAt = function( index ){
- this.observerList.splice( index, 1 );
- };
- //目标
- function Subject(){
- this.observers = new ObserverList();
- }
- Subject.prototype.addObserver = function( observer ){
- this.observers.add( observer );
- };
- Subject.prototype.removeObserver = function( observer ){
- this.observers.removeAt( this.observers.indexOf( observer, 0 ) );
- };
- Subject.prototype.notify = function( context ){
- var observerCount = this.observers.count();
- for(var i=0; i < observerCount; i++){
- this.observers.get(i).update( context );
- }
- };
- //观察者
- function Observer(){
- this.update = function(){
- // ...
- };
- }
发布/订阅模式实现代码(JavaScript经典版):
- var pubsub = {};
- (function(myObject) {
- // Storage for topics that can be broadcast
- // or listened to
- var topics = {};
- // An topic identifier
- var subUid = -1;
- // Publish or broadcast events of interest
- // with a specific topic name and arguments
- // such as the data to pass along
- myObject.publish = function( topic, args ) {
- if ( !topics[topic] ) {
- return false;
- }
- var subscribers = topics[topic],
- len = subscribers ? subscribers.length : 0;
- while (len--) {
- subscribers[len].func( topic, args );
- }
- return this;
- };
- // Subscribe to events of interest
- // with a specific topic name and a
- // callback function, to be executed
- // when the topic/event is observed
- myObject.subscribe = function( topic, func ) {
- if (!topics[topic]) {
- topics[topic] = [];
- }
- var token = ( ++subUid ).toString();
- topics[topic].push({
- token: token,
- func: func
- });
- return token;
- };
- // Unsubscribe from a specific
- // topic, based on a tokenized reference
- // to the subscription
- myObject.unsubscribe = function( token ) {
- for ( var m in topics ) {
- if ( topics[m] ) {
- for ( var i = 0, j = topics[m].length; i < j; i++ ) {
- if ( topics[m][i].token === token ) {
- topics[m].splice( i, 1 );
- return token;
- }
- }
- }
- }
- return this;
- };
- }( pubsub ));
观察者模式(Observer)和发布(Publish/订阅模式(Subscribe)的区别的更多相关文章
- 观察者模式(Observer)发布、订阅模式
观察者模式定义了对象之间一对多的依赖关系,这样一来,当一个对象改变时,他的所有依赖者都会收到通知并自动更新. 模式中的角色 1.抽象主题(Subject):它把所有观察者对象的引用保存到一个聚集里 ...
- node.js 中 events emitter 的实现(发布、订阅模式)
const EventEmitter = require('events'); const myEmitter = new EventEmitter(); myEmitter.on('event', ...
- JS模式---发布、订阅模式
发布订阅模式又叫观察者模式,它定义一种一对多的依赖关系, 当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知. document.body.addEventListener('click', ...
- Zookeeper学习(八):Zookeeper的数据发布与订阅模式
http://blog.csdn.net/ZuoAnYinXiang/article/category/6104448 1.发布订阅的基本概念 1.发布订阅模式可以看成一对多的关系:多 ...
- 知方可补不足~SQL2008中的发布与订阅模式
回到目录 作用:完成数据库与数据库的数据同步 原理:源数据库发布需要同时的表,存储过程,或者函数:目标数据库去订阅它,当源发生变化时,目标数据库自己同步,注意,由于这个过程是SQL自动完成的,所以要求 ...
- Redis 发布与订阅模式
subscribe 订阅 publish 发布 频道 发布内容
- 知方可补不足~SQL2008中的发布与订阅模式~续
回到目录 上一回介绍了如何在sql2008中建立一个数据库的发布者,今天来说一下如何建立一个订阅者,其实订阅者也是一个数据库,而这个数据库是和发布者的数据结构相同的库,它们之间通过SQL代理进行数据上 ...
- javascript中的发布订阅模式与观察者模式
这里了解一下JavaScript中的发布订阅模式和观察者模式,观察者模式是24种基础设计模式之一. 设计模式的背景 设计模式并非是软件开发的专业术语,实际上设计模式最早诞生于建筑学. 设计模式的定义是 ...
- js设计模式之发布订阅模式
1. 定义 发布-订阅模式其实是一种对象间一对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都将得到状态改变的通知. 订阅者(Subscriber)把自己想订阅的事件注册(Subscri ...
随机推荐
- Vue笔记:使用 axios 中 this 指向问题
问题背景 在vue中使用axios做网络请求的时候,会遇到this不指向vue,而为undefined. 如下图所示,我们有一个 login 方法,希望在登录成功之后路由到主页,但通过 this.$r ...
- TypeError: 'NoneType' object is not subscriptable
运行,显示TypeError: 'NoneType' object is not subscriptable错误信息,原因是变量使用了系统内置的关键字list 重新定义下这个变量就好了
- JAVA WEB开发环境与搭建
一:jdk下载与安装 (1)官网下载地址:https://www.oracle.com/technetwork/java/javase/downloads/jdk11-downloads-506665 ...
- Numpy系列(十)- 掩码数组
简介 有时候数据集中存在缺失.异常或者无效的数值,我们可以标记该元素为被屏蔽(无效)状态. import numpy as np import numpy.ma as ma x = np.array( ...
- golang net包使用
创建简单的响应服务器 package main import ( "net/http" ) func handlerFunc(w http.ResponseWriter, r *h ...
- CopyOnWriteArrayList真的完全线程安全吗
我之前书上看到的说法是:Vector是相对线程安全,CopyOnWriteArrayList是绝对线程安全 这种说法其实有些问题,CopyOnWriteArrayList在某些场景下还是会报错的 Co ...
- 第八节: EF的性能篇(一) 之 EF自有方法的性能测试
一. 开发中常见的性能问题 我们在日常开发过程中,由于一些不好的习惯,经常会导致所写的代码性能低下,却毫无发觉,下面就总结一下常见的一些性能问题. 1. 真假分页 ① 假分页: db.xxx.toLi ...
- django - 总结 - cookie|session
Cookie是通过HTTP请求和响应头在客户端和服务器端传递的. 在Web开发中,使用session来完成会话跟踪,session底层依赖Cookie技术. --------------------- ...
- [物理学与PDEs]第1章习题7 载流线圈的磁场
设一半径为 $R$ 的圆周电路上的电流强度为 $I$. 试计算在通过圆心垂直于圆周所在平面的直线上, 由该圆周电路产生的磁场的磁感强度. 解答: 由对称性知在该直线 $l$ 上, ${\bf B}$ ...
- 运维工作笔记——基于centos7.3的多台服务期时间同步
1. 确认服务器版本 2.查看本机时间 3.可以同过date进行时间更改 4.yum安装ntp服务(服务端与客户端都需要安装) yum install -y ntp 5.在服务端192.1 ...