观察者模式又被称为发布-订阅模式,是设计模式中的一种行为型模式;前端
定义:vue
观察者模式定义了一种一对多的对象依赖关系,当被依赖的对象的状态发生了改变,全部依赖它的对象都会获得通知;设计模式
白话解释:数组
假如你去苹果专卖店买最新款的iphone11,由于iphone11刚出来不久,正处旺季,供货不足;当你去专卖店的时候,店员告诉你暂时没货了,可是你能够留下你的联系方式,若是货到了,会第一时间通知;固然你确定不会天天都去专卖店问iphone11到货没有,也不会每天给专卖店打电话,由于你有你本身的工做和生活,不可能有那么多闲暇时间;因此此时,店员让你留下联系方式,到货了第一时间通知你,不会给你带来麻烦,而你只须要等着专卖店的电话便可;而这种方法就是一种典型的观察者模式;
浏览器
首先咱们仍是来分析一下:app
1.订阅方法:咱们把联系方式给专卖店店员是属于一种消息订阅的消息,由于只有这样你才能及时的知道iphone11到货了,全部咱们须要一个订阅行为的具体方法;框架
2.预订列表:要知道iphone11是属于新版iphone,因此确定不会是只有你一我的去预订,因此店员为了方便统计还须要一个预订列表来统计全部的预订者的联系方式以及预订手机版本信息,因此咱们这里先给它定义为一个对象;key表明是预订者的联系方式,value表明预订手机版本信息;iphone
3.发布方法:当iphone11到货的时候,专卖店确定要根据预订列表来进行统一发布消息("iphone11到货了,你们快来抢!!!"),因此专卖店须要一个发布方法来实行具体的发布行为;、函数
4.取消订阅:万物相对,能订阅确定就能取消订阅;在等待iphone11到货通知的时候,你急着用手机,因此直接买了华为的某款,因此iphone11暂时对你来讲需求不大,由于你已经有了手机因此专卖店的iphone11是否到货对你来讲没有任何意义了;因此此时你不想被打扰,须要取消订阅消息;因此咱们须要一个取消订阅方法来实现具体的取消订阅的行为;学习
观察者模式的应用场景:
一、DOM事件
若是你是一个前端开发人员,无论你读这篇文章以前是否已经了解观察者模式,可是我能确定你已经用过观察者模式;
document.body.addEventListener('click', function() { console.log('hello world!'); });
这段代码看着眼熟吗?是的,这是一个DOM事件的监听;咱们经过给body订阅click事件(click至关于上面的订阅方法),由于浏览器并不知道你何时点击鼠标,因此等你触发click事件的时候才会触发函数给你发布通知(发布方法);DOM事件就是一个观察者模式的实现;
二、vue双向绑定v-model
咱们做为前端开发人员,确定知道vue是一个MVVM模式的框架;vue的核心就是双向绑定,那么双向绑定的实现实际上就是一种观察者模式;由于你首先绑定了一个数据以后(订阅方法),浏览器并不知道你何时修改,你页面上全部绑定了该数据或者依赖该数据的节点其实就是一个预订列表,只有等你修改了该数据的值的时候,vue才会通知(发布方法)到依赖该数据的方法/数据进行相应的操做或刷新;
固然观察者模式毫不仅限于这俩种实现场景,在咱们的生活中、业务场景中有不少观察者模式的示例,以前咱们第一篇工厂模式介绍设计模式的时候就说过了,设计模式是一种解决问题的思路而非一种固定的公式,那么咱们怎么实现观察者模式呢?
观察者模式的实现:
//定义商家 var merchants = {}; //定义预订列表 merchants.orderList = {}; //将增长的预约者添加到预订列表中 (订阅方法) merchants.listen = function(id,info){ //若是存在 if(!this.orderList[id]){ // (预订列表) this.orderList[id] = []; } // 将用户的预约的产品信息存入到数组中 this.orderList[id].push(info); } //发布信息(发布方法) merchants.publish = function(){ var id = Array.prototype.shift.call(arguments); var infos = this.orderList[id]; if(!infos || infos.length === 0){ console.log("您尚未预约信息"); return false; } for(var i = 0;i < infos.length;i++){ console.log("预约成功"); console.log("尊敬的用户:") infos[i].apply(this,arguments); console.log("到货了"); } } //取消订阅 merchants.remove = function(id,fn){ var infos = this.orderList[id]; if(!infos){ return false} if(!fn){ console.log(123); }else{ for(var i = 0;i < infos.length;i++){ if(infos[i] === fn){ infos.splice(i,1); } } } } let customeA = function(){ console.log("黑色尊享版一台"); } merchants.listen("15172103336",customeA); merchants.remove("15172103336",customeA); merchants.publish("15172103336");
上面的代码稍微有点长,不过没有很难;首先咱们是定义了一个对象是做为商家,而后定义了一个空的对象做为预订列表,再一步步的实现咱们的订阅方法和发布以及取消订阅的方法;逻辑不复杂,可是有一些语法须要讲解一下:
发布方法中的var id = Array.prototype.shift.call(arguments);这句的意思是将merchants.publish("15172103336");方法调用的时候第一个参数返回给它而后复制为id,因此其实此时的id值为”15172103336“;
infos[i].apply(this,arguments);这个方法也不是特别好理解,首先infos里装的是预订者的手机号码以及手机版本信息,因此咱们infos[i].apply(this,arguments);这个方法其实就是将"15172103336"对应的手机版本信息函数进行调用了一遍;实际上等于infos[i](arguments);
观察者模式不论是在前端领域仍是在现实生活中的应用都是有很常见的场景,学好观察者模式有利用咱们学习vue的源码知识,固然不只限于此,因此观察者模式值得咱们好好学习,一句话:"你品,你细品!" 今天付出的努力,在往后总会换成工资来回报你的!哈哈哈