精华内容
下载资源
问答
  • 发布订阅模式

    2019-11-27 21:58:16
    观察者模式有一个别名叫做 发布订阅模式,就像你订阅了一份报纸,其他人也订阅了和你一样的报纸,当报社发布报纸时,订阅了这个报纸的人就能得到新报纸了 发布订阅模式 上面说过,发布订阅模式是观察者模式的一个...

    观察者模式

    观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改时,所有依赖于它的 对象的都会得到通知,并且会自动更新,它其实就是观察者和被观察者之间的通信
    观察者模式有一个别名叫做 发布订阅模式,就像你订阅了一份报纸,其他人也订阅了和你一样的报纸,当报社发布报纸时,订阅了这个报纸的人就能得到新报纸了

    发布订阅模式

    上面说过,发布订阅模式是观察者模式的一个别称,但 发布订阅 模式现在也越来越强大,组件独立于观察者模式了
    在现在的 发布订阅 模式中,发布者的消息不会直接传给订阅者,它们之间有一个第三方,由这个第三方将消息 传给订阅者
    在这里插入图片描述

    观察者模式: 观察者(Observer)直接订阅(Subscribe)主题(Subject),而当主题被激活的时候,会触发(Fire Event)观察者里的事件。
    发布订阅模式: 订阅者(Subscriber)把自己想订阅的事件注册(Subscribe)到调度中心(Topic),当发布者(Publisher)发布该事件(Publish topic)到调度中心,也就是该事件触发时,由调度中心统一调度(Fire Event)订阅者注册到调度中心的处理代码。

    发布订阅模式只是一种模式,具体的实现还是要我们自己根据实际情况去编写代码

    const  shop = {}; // 首先定义一个商铺
    
    shop.list = [];  // 定义商铺里的商品信息列表
    
    shop.listen = function(fn) { // 添加订阅者
        this.list.push(fn); // 将订阅的商品添加进入商品心里列表
    }  
    
    shop.sell = function(){  //发布者
        for( var i = 0, fn; fn = this.list[ i++ ]; ){
            fn.apply( this, arguments ); // (2) // arguments 是发布消息参数
        }
    }
    
    // 这是来了一个顾客询问手机的价格,那么
    shop.listen(function(iphone, price) {
        console.log('手机型号' + iphone);
        console.log('价格' + price)
    })
    
    // 发布消息,本店卖IphoneX, 价格7000
    shop.sell('IphoneX', 7000);
    
    shop.sell('Iphone11', 9000);
    
    // 输出 手机型号IphoneX, 价格7000
    // 输出 手机型号Iphone11, 价格9000
    
    展开全文
  • 本篇文章给大家带来的内容是关于javascript发布订阅模式的详解(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。发布订阅模式事件发布/订阅模式 (PubSub) 在异步编程中帮助我们完成更松的...

    本篇文章给大家带来的内容是关于javascript发布订阅模式的详解(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

    发布订阅模式

    事件发布/订阅模式 (PubSub) 在异步编程中帮助我们完成更松的解耦,甚至在 MVC、MVVC 的架构中以及设计模式中也少不了发布-订阅模式的参与。

    优点:在异步编程中实现更深的解耦

    缺点:如果过多的使用发布订阅模式,会增加维护的难度

    实现发布订阅模式var Event = function() {

    this.obj = {}

    }

    Event.prototype.on = function(eventType,fn) {

    if(!this.obj[eventType]) {

    this.obj[eventType] = []

    }

    this.obj[eventType].push(fn)

    }

    Event.prototype.emit = function() {

    // 取第一个参数,作为eventType

    var eventType = Array.prototype.shift.call(arguments);

    // 获取事件数组

    var arr = this.obj[eventType];

    var len = arr.length;

    // 循环数组,一次执行其中的函数

    for(var i=0;i

    // 直接调用arr[i],其this指向为undefined(严格模式下)

    // 因此用apply将this指向arr[i]

    // 数组shift函数取出第一个参数,将剩下的参数传入函数中

    arr[i].apply(arr[i],arguments)

    }

    }

    var ev = new Event()

    ev.on('click',function(a) { // 订阅

    console.log(a)

    })

    ev.emit('click',1) // 发布

    以上代码只能实现先订阅,再发布。直接发布就会报错。如何实现可以先发布,然后订阅?var Event = function() {

    this.obj = {};

    this.cacheList = [];

    }

    Event.prototype.emit = function() {

    const args = arguments; //函数参数

    const that = this; //this指向,保持cache函数的this指向

    function cache() {

    var eventType = Array.prototype.shift.call(arg)

    var arr = that.obj[eventType]

    for (let i = 0; i < arr.length; i++) {

    arr[i].apply(arr[i], arg)

    }

    }

    this.cacheList.push(cache) // 采用闭包,保持对emit函数中参数和that的引用

    }

    Event.prototype.on = function(eventType,fn) {

    if(!this.obj[eventType]) {

    this.obj[eventType] = []

    }

    this.obj[eventType].push(fn)

    // 在订阅函数中执行emit函数中缓存的函数

    for (let i = 0; i < this.cacheList.length; i++) {

    this.cacheList[i]()

    }

    }

    改成这样后就实现了先发布函数,再订阅的过程。但是也只能先发布,然后再订阅,反过来就行不通。

    展开全文
  • 主要介绍了JavaScript设计模式之观察者模式与发布订阅模式,结合实例形式详细分析了JavaScript观察者模式与发布订阅模式相关概念、原理
  • 发布订阅模式理解

    2020-03-25 10:11:38
    发布订阅模式理解 1.发布-订阅模式 发布订阅模式是一种一对多的对象对应关系,多个观察者同时监听某一个对象,当该对象发生改变时,就会执行一个发布事件,这个发布事件会通知所有的事件订阅者,事件订阅者根据得到...

    发布订阅模式理解

    1.发布-订阅模式

    发布订阅模式是一种一对多的对象对应关系,多个观察者同时监听某一个对象,当该对象发生改变时,就会执行一个发布事件,这个发布事件会通知所有的事件订阅者,事件订阅者根据得到的数据进而改变自己的状态。
    一个完整的发布订阅模式,由发布者、订阅者和消息管理器组成。
    在这里插入图片描述
    2.发布订阅模式的实现思路

    1)创建一个发布者对象,并在其上添加一个列表属性,用于存放订阅者的回调函数
    2)发布者发布消息,将消息依次传给每一个列表中的回调函数并触发它

    简单的demo:

    var shoeObj = {
    	//存放订阅者的回调函数
    	list:[],
    	//将订阅者的回调函数放在列表中
    	listen(){
    		shoeObj.list.push(fn);
    	},
    	//发布消息
    	trigger(){
    		for(var i = 0,fn; fn = this.list[i++];) {
    			//将参数应用于每一个回调函数
            	fn.apply(this,arguments); 
        	}
    	}
    }; 
    //小红的订阅数据
    shoeObj.listen(function(color,size){
    	console.log("颜色是:"+color);
    	console.log("大小是:"+size);
    })
    //小明的订阅数据
    shoeObj.listen(function(color,size){
    	console.log(123,color,size);
    })
    //发布数据
    shoeObj.trigger("红色",40);
    shoeObj.trigger("黑色",42);
    

    输出结果:
    在这里插入图片描述
    增加key:让用户只接收自己感兴趣的信息

    var shoeObj = {
    		//存放订阅者的回调函数
    		list:[],
    		//将订阅者的回调函数放在列表中
    		listen(key,fn){
    			//为每一个key创建一个列表
    			if (!this.list[key]){
    				this.list[key]=[];
    			}
    			shoeObj.list[key].push(fn);
    		},
    		//发布消息,将信息发布给每一个回调函数
    		trigger(){
    			var key = Array.prototype.shift.call(arguments); // 取出消息类型名称
    		    var fns = this.list[key];  // 取出该key对应的回调函数的集合
    
    		    // 如果没有订阅过该消息的话,则返回
    		    if(!fns || fns.length === 0) {
    		        return;
    		    }
    			for(var i = 0,fn; fn = fns[i++];) {
    				//将参数应用于每一个回调函数
    	        	fn.apply(this,arguments); 
    	    	}
    		}
    	}; 
    	//小红的订阅数据,key是‘red’
    	shoeObj.listen('red',function(size){
    		console.log("大小是:"+size);
    	})
    	//小明的订阅数据,key是‘black’
    	shoeObj.listen('black',function(size){
    		console.log(123,size);
    	})
    	//发布消息
    	shoeObj.trigger("red",40);
    	shoeObj.trigger("black",42);
    

    输出结果:在这里插入图片描述
    这样,订阅者就只订阅了自己感兴趣的信息了。

    将代码进行封装,可以应用于各种场景:

    var event = {
    		//存放订阅者的回调函数
    		list:[],
    		//将订阅者的回调函数放在列表中
    		listen(key,fn){
    			//为每一个key创建一个列表
    			if (!this.list[key]){
    				this.list[key]=[];
    			}
    			this.list[key].push(fn);
    		},
    		//发布消息,将信息发布给每一个回调函数
    		trigger(){
    			var key = Array.prototype.shift.call(arguments); // 取出消息类型名称
    		    var fns = this.list[key];  // 取出该key对应的回调函数的集合
    
    		    // 如果没有订阅过该消息的话,则返回
    		    if(!fns || fns.length === 0) {
    		        return;
    		    }
    			for(var i = 0,fn; fn = fns[i++];) {
    				//将参数应用于每一个回调函数
    	        	fn.apply(this,arguments); 
    	    	}
    		}
    	}; 
    	//初始化普通对象,使其具有发布订阅功能
    	var initEvent = function(obj) {
    	    for(var i in event) {
    	        obj[i] = event[i];
    	    }
    	};
    

    加入取消订阅:

    var event = {
    		//存放订阅者的回调函数
    		list:[],
    		//将订阅者的回调函数放在列表中
    		listen(key,fn){
    			//为每一个key创建一个列表
    			if (!this.list[key]){
    				this.list[key]=[];
    			}
    			this.list[key].push(fn);
    		},
    		//发布消息,将信息发布给每一个回调函数
    		trigger(){
    			var key = Array.prototype.shift.call(arguments); // 取出消息类型名称
    		    var fns = this.list[key];  // 取出该key对应的回调函数的集合
    
    		    // 如果没有订阅过该消息的话,则返回
    		    if(!fns || fns.length === 0) {
    		        return;
    		    }
    			for(var i = 0,fn; fn = fns[i++];) {
    				//将参数应用于每一个回调函数
    	        	fn.apply(this,arguments); 
    	    	}
    		},
    		//取消订阅
    		remove(key,fn){
    			var fns = this.list[key];
    		    // 如果key对应的消息没有订阅过的话,则返回
    		    if(!fns) {
    		        return false;
    		    }
    		    // 如果没有传入具体的回调函数,表示需要取消key对应消息的所有订阅
    		    if(!fn) {
    		        fn && (fns.length = 0);
    		    }else {
    		        for(var i = fns.length - 1; i >= 0; i--) {
    		            var _fn = fns[i];
    		            if(_fn === fn) {
    		                fns.splice(i,1); // 删除订阅者的回调函数
    		            }
    		        }
    		    }
    		}
    	}; 
    	//初始化普通对象,使其具有发布订阅功能
    	var initEvent = function(obj) {
    	    for(var i in event) {
    	        obj[i] = event[i];
    	    }
    	};
    

    封装发布订阅模式:

    //发布订阅模式
    class eventEmitter(){
    
    	constructor(){
    		this.list = {};
    	}
    
    	listen(key,fn){
    		if(!this.list[key]){
    			this.list[key] = [];
    		}
    		this.list[key].push(fn);
    	}
    
    	publish(){
    		let key = Array.prototype.shift.call(arguments);
    		let fns = this.list[key];
    		if (!fns||fns.length===0){
    			return ;
    		}
    		for(let i=0;i<fns.length;i++){
    			fns[i].apply(this,arguments);
    		}
    	}
    
    	remove(key,fn){
    		let fns = this.list[key];
    		if (!fns || fns.length === 0){
    			return ;
    		}
    		if (!fn){
    			this.list[key]=[];
    		} else {
    			let fnsFilter = fns.filter((it,ind)=>{
    				return it != fn;
    			})
    			this.list[key]=fnsFilter;
    		}
    	}
    
    }
    export default new eventEmitter();
    

    3.为什么要用发布订阅模式?
    如果一个数据或者事件的变化会对很多事件产生影响,比如我们在初始化接口之后会得到初始化数据,当初始化接口返回成功时,需要执行其他的几个方法,正常情况下,我们会注册一个函数,在这个函数中写n个函数的执行,但是如果利用发布订阅模式,其他几个函数可以订阅该接口的成功事件,然后根据订阅接收到的数据执行自己的函数。
    优点:耦合性低,便于代码的维护

    参考博客:https://www.cnblogs.com/itgezhu/p/10947405.html

    展开全文
  • 一 前言虽然有消息队列,我们还是要了解一下redis发布订阅模式哟!!!!!二发布订阅模式PUBLISH 命令向通道发送信息,此客户端称为publisher 发布者;SUBSCRIBE 向命令通道订阅信息,此客户端称为subscriber 订阅...

    47721cd1cf642954339859c3707251c8.png

    一 前言

    虽然有消息队列,我们还是要了解一下redis发布订阅模式哟!!!!!

    二发布订阅模式

    5ade93be76fced6c1643e0312bff0d13.png
    • PUBLISH 命令向通道发送信息,此客户端称为publisher 发布者;
    • SUBSCRIBE 向命令通道订阅信息,此客户端称为subscriber 订阅者;
    • redis 中 发布订阅模块的名字叫着 PubSub,也就是 PublisherSubscriber;
    • 一个发布者向一个通道发送消息,订阅者可以向多个通道订阅消息;当发布者向通道发布消息后,如果有订阅者订阅该通道,订阅者就会收到消息;这有点像电台,我收听了一个电台的频道,当频道发送消息后,我就能收到消息;

    三PUBSub模块命令

    • subscribe: 订阅一个或者多个频道;
    • unsubscribe: 退订一个或者多个频道;
    • publish: 向通道发送消息;
    • psubscribe: 订阅给定模式相匹配的所有频道;
    • punsubscribe: 退订 给定模式所有的频道,若未指定模式,退订所有频道;

    具体的命令使用方式 可以使用 help 命令 ;示例如下:

    help subscribe

    四客户端实现

    通过指令SUBSCRIBE订阅一个频道,如果频道不存在时则新建一个频道;此时此客户端就是订阅者

    127.0.0.1:6379> subscribe zszxz
    Reading messages... (press Ctrl-C to quit)
    1) "subscribe"
    2) "zszxz"
    3) (integer) 1
    ​

    通过指令publish向通道发送一个消息;此时客户端就是发布者

    127.0.0.1:6379> publish zszxz "l miss you"
    (integer) 1
    127.0.0.1:6379>

    我们再看看 客户端就收到消息了

    127.0.0.1:6379> subscribe zszxz
    Reading messages... (press Ctrl-C to quit)
    1) "subscribe"
    2) "zszxz"
    3) (integer) 1
    1) "message"
    2) "zszxz"
    3) "l miss you"

    五java 实现

    定义2个订阅者用于订阅频道的消息,在使用jedis 时 需要 继承 JedisPubSub 类, 并重写 onMessage 方法; 订阅者可以在该方法里面进行消息的业务逻辑处理;

    订阅者 1

    /**
    

    订阅者2

    /**
    

    发布者

    /**
    

    测试类、

    注意redis 的 发布订阅模式 是阻塞模式 ,一个订阅者需要 重新起一个线程;

    @Autowired
        

    六 缺点

    • PubSub 的生产者来一个消息会直接传递给消费者。如果没有消费者,消息会直接丢弃。如果有多个消费者,一个消费者突然挂掉,生产者会继续发送消息,另外的消费者可以持续收到消息。但是挂掉的消费者重新连上后,断连期间的消息会彻底丢失;
    • 如果 Redis 停机重启,PubSub 的消息是不会持久化

    公众号:知识追寻者

    展开全文
  • 之前一直对观察者模式和发布订阅模式的区别理解不深,正好这段时间在看vue源码的分析,vue数据双向绑定也用到了发布订阅模式,于是又把这两者探究了一番,今天做个笔记加强印象。观察者模式和发布订阅模式最大的区别...
  • 发布——订阅模式简介 发布——订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,多个观察者对象都依赖于一个目标对象,当目标对象的...以上代码就是发布订阅模式,需要监控用户点击button按钮,执行里
  • js设计模式 发布订阅模式发布订阅模式 发布订阅模式 发布订阅模式中有一个注册中心,有订阅和发布方法,订阅者需要带着方法去订阅一个事件,当这个事件被发布时,订阅者执行这个方法 import * as _ from 'lodash'; /...
  • 发布订阅模式和观察者模式发布订阅模式观察者模式发布订阅模式 VS 观察者模式 发布订阅模式 订阅者、发布者、信号中心 // 具体实现可参考:https://blog.csdn.net/baidu_33591715/article/details/114258885 // ...
  • 主要介绍了浅谈发布订阅模式与观察者模式,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 一 前言虽然有消息队列,我们还是要了解一下redis发布订阅模式哟!!!!!二发布订阅模式PUBLISH 命令向通道发送信息,此客户端称为publisher 发布者;SUBSCRIBE 向命令通道订阅信息,此客户端称为subscriber 订阅...
  • 一 前言虽然有消息队列,我们还是要了解一下redis发布订阅模式哟!!!!!二发布订阅模式PUBLISH 命令向通道发送信息,此客户端称为publisher 发布者;SUBSCRIBE 向命令通道订阅信息,此客户端称为subscriber 订阅...
  • 实现发布订阅模式

    2020-11-05 14:41:11
    1.你去买东西断货了, 老板让你留下联系方式, 到货了给你打电话, 这就是发布订阅模式 2.老板就是发布者, 你就是订阅者 3.订阅者将电话添加到了发布者的缓存列表中(电话簿) 4.当发布者到货后就会遍历缓存列表依次通知...
  • 有一回面试,面试官问:观察者模式,和发布订阅模式,有什么区别?我脑海中立刻闪现了《Head First设计模式》里讲的:Publishers + Subscribers = Observer Pattern“哼哼,我知道答案了,兄dei!”,我内心无比鸡冻...
  • 理解发布订阅模式

    2021-01-14 19:52:15
    理解发布订阅模式 https://www.cnblogs.com/tugenhua0707/p/4687947.html
  • 发布订阅模式EventBusregister:向集合中添加post: 从集合中获取 观察者模式与发布订阅者模式 1.观察者模式 Observerable依赖Observer 2.发布订阅模式 Publisher并不依赖Subscriber,Publisher和Subscriber并不存在...
  • javascript 设计模式 发布订阅模式
  • JS 发布订阅模式

    2018-10-25 12:53:52
    发布订阅模式 事件发布/订阅模式 (PubSub) 在异步编程中帮助我们完成更松的解耦,甚至在 MVC、MVVC 的架构中以及设计模式中也少不了发布-订阅模式的参与。 优点:在异步编程中实现更深的解耦 缺点:如果过多的使用...
  • GitHub地址:abel-max/Java-Study-Note目录发布/订阅者模式的优点实现发布/订阅者模式需要考虑的点何时应使用发布/订阅者模式发布/订阅者模式与观察者模式 熟悉消息中间件的同学应该对发布/订阅模式(Publish ...
  • 观察者模式和发布订阅模式区别观察者模式和发布订阅模式区别:一、从表面上看:二、往更深层次讲:三、从使用层面上讲:四、总结: 观察者模式和发布订阅模式区别: 一、从表面上看: 观察者模式里,只有两个角色 ...
  • 经常会有面试题问发布订阅模式,很多童鞋都一脸懵逼,根本不知道在问什么,甚至觉得自己根本用不上这玩意。 其实,市面上的各大框架的事件处理,特别是组件通讯都基于发布订阅模式实现,比如vue的vuex,reace的...
  • 手写发布订阅模式 EventEmitter

    千次阅读 2019-10-22 16:28:40
    手写发布订阅模式 EventEmitter 1.简介 最近发现好多大厂面试题里都有手写发布订阅模式 EventEmitter,原因是 vue 和 react 的非父子组件的通信就是靠他实现的,下面是一个简易版的 EventEmitter。 2.代码 // 发布...
  • 大概很多人都和我一样,觉得发布订阅模式里的Publisher,就是观察者模式里的Subject,而Subscriber,就是Observer。Publisher变化时,就主动去通知Subscriber。 其实并不是。 在发布订阅模式里,发布者,并不会...
  • 在网上看到许多关于观察者模式和发布订阅模式的博文,发现很多人都认为观察者模式即发布订阅模式,经过进一步的学习和理解,我认为观察者模式和发布订阅模式还是有一些区别的,下面谈谈我对观察者模式和发布订阅模式...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 15,688
精华内容 6,275
关键字:

发布订阅模式