发布订阅模式理解

发布订阅模式理解

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

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值