最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

js发布订阅者模式详细的个人理解

来源:懂视网 责编:小采 时间:2020-11-27 20:23:13
文档

js发布订阅者模式详细的个人理解

js发布订阅者模式详细的个人理解:先摘抄一下javascript设计模式与开发实践一书中的文字介绍//现实中的发布订阅模式 小明最近看上了一套房子,到了售楼处之后才被告知,该楼盘的房子早已售罄。好在售楼MM告诉小明,不久后还有一些尾盘推出,开发商正在办理相关手续,手续办好后便可以购买。
推荐度:
导读js发布订阅者模式详细的个人理解:先摘抄一下javascript设计模式与开发实践一书中的文字介绍//现实中的发布订阅模式 小明最近看上了一套房子,到了售楼处之后才被告知,该楼盘的房子早已售罄。好在售楼MM告诉小明,不久后还有一些尾盘推出,开发商正在办理相关手续,手续办好后便可以购买。

先摘抄一下javascript设计模式与开发实践一书中的文字介绍//现实中的发布订阅模式
小明最近看上了一套房子,到了售楼处之后才被告知,该楼盘的房子早已售罄。好在售楼MM告诉小明,不久后还有一些尾盘推出,开发商正在办理相关手续,手续办好后便可以购买。 但到底是什么时候,目前还没有人能够知道。于是小明记下了售楼处的电话,以后每天都会打电话过去询问是不是已经到了购买时间。除了小明,还有小红、小强、小龙也会每天向售楼处咨询这个问题。一个星期过后,售MM 决 定辞职,因为厌倦了每天回答1000 个相同内容的电话。

当然现实中没有这么笨的销售公司,实际上故事是这样的:小明离开之前,把电话号码留在了售楼处。售楼MM 答应他,新楼盘一推出就马上发信息通知小明。小红、小强和小龙也是一样,他们的电话号都被记在售楼处的花名册上,新楼盘推出的时候,售楼MM会翻开花名册,遍历上面的电话号码,依次发送一条短信来通知他们。在刚刚的例子中,发送短信通知就是一个典型的发布—订阅模式,小明、小红等购买者都是订阅者,他们订阅了房子开售的消息。售楼处作为发布者,会在合适的时候遍历花名册上的电话 号码,依次给购房者发布消息。

可以发现,在这个例子中使用发布—订阅模式有着显而易见的优点。购房者不用再天天给售楼处打电话咨询开售时间,在合适的时间点,售楼处作为发布者会通知这些消息订阅者。购房者和售楼处之间不再强耦合在一起,当有新的购房者出现时,他只需把手机号码留在售楼处,售楼处不关心购房者的任何情况,不管购房者是男是女还是一只猴子。 而售 楼处的任何变动也不会影响购买者,比如售楼MM 离职,售楼处从一楼搬到二楼,这些 改变都跟购房者无关,只要售楼处记得发短信这件事情。

首先要指定好谁充当发布者(比如售楼处);然后给发布者添加一个缓存列表,用于存放回调函数以便通知订阅者(售楼处的花名册); 最后发布消息的时候,发布者会遍历这个缓存列表,依次触发里面存放的订阅者回调函 数(遍历花名册,挨个发短信)。另外,我们还可以往回调函数里填入一些参数,订阅者可以接收这些参数。这是很有必要的,比如售楼处可以在发给订阅者的短信里加上房子的单价、面积、容积率等信息,订阅者接收到这些信息之后可以进行各自的处理:

  • <!DOCTYPE html>
    <html lang="en">
    <head>
     <meta charset="UTF-8">
     <title>观察者模式</title>
    </head>
    <body>
    <button id="count">点我</button>
    <p id="show"></p>
    <script>
     //我的个人理解
     //发布者首先需要一个对象来保存事件的回调函数,这个对象的属性就是事件类型,比如{"click":[fn1,fn2],"mouseover":[fn3,fn4]}
     //订阅事件:首先要判断这个事件类型是否存在当前的对象上,如果不存在那就初始化一下就是添加这个属性,并且给这个属性的值设置为空数组
     //如果已经存在了那么久开始把该对调函数push进去对应的属性的值, 该值为一个数组
     //发布事件:发布事件就要一个个的通知订阅者,还有就是你发布了什么事件。这里要有if判断,
     // 先从参数中取出要发布事件的key,然后获取到key对应的回调函数数组,取出数组后先判断数组是否存在或者数组长度是否为0,如果不存在或者为0
     //就结束程序,若上述条件不成立就执行for循环,一次遍历回调函数数组,并执行里面的函数,这里需要改变回调函数的this指向。防止丢之
     //this。
     //移出事件:先判断要移出的key的值是否为空,若空则退出程序否则再判断是否传入了要移出哪个回调函数,若空,则认为要移出全部的函数,就把数组长度设置为0
     //
     //下面是js设计模式与开发实践上的实现过程
     var Event=(function(){
     var clientList={},
     listen,
     trigger,
     remove;
     listen=function(key,fn){
     if(!clientList[key]){
     clientList[key]=[];
     }
     clientList[key].push(fn);
     };
     trigger=function(){
     var key=Array.prototype.shift.call(arguments),
     cb=clientList[key];
     if(!cb||cb.length==0){
     return false;//如果没有保存回调函数就退出程序
     }
     for(var i=0;i<cb.length;i++ ){
     cb[i].apply(this,arguments);//为什么要用applly呢,这是为了把触发时传入的参数传入给cb[i]对应的回调函数里面使用并且还要改变this指向
     }
     };
     remove=function (key,fn) {
    
     var cb=clientList[key];
     if(!cb){
     return false;//如果要移除的key的值为空就代表没有人订阅该key和设置回调函数则直接返回
     }
     if(!fn){//如果没有传入具体的回调函数,表示需要取消key对应的消息的所有订阅
     cb&&(cb.length=0);//这里cb是已经存在了就把cb的length设置为0.我有疑问,到这里其实cb不会不存在了吧上面如果不存在就退出了如何会走到这一步?
     }
     else{
     for(var l=0;l<cb.length;l++){
     var _cb=cb[l];
     if(_cb===fn){//寻找哪个和要删除的回调函数一样
     cb.splice(l,1);//从l处删除一个元素
     }
     }
     }
     };
     return {
     listen:listen,
     trigger:trigger,
     remove:remove
     }//这里返回这个对象其实是相当于中介代理的意思,请看下面的实际例子解释:
    //我们给每个发布者对象都添加了listen 和trigger 方法,以及一个缓存列表clientList,
    //这其实是一种资源浪费。
    //小明跟售楼处对象还是存在一定的耦合性,小明至少要知道售楼处对象的名字是
    //才能顺利的订阅到事件。
    //因此返回一个通用的对象,不必知道这个对象的名字,只需要把这个对象的一个引用给一个变量就行了
     })();
     Event.listen("A",fn1=function(data){
     console.log(data);
     })
     Event.listen("A",fn2=function(data){
     console.log(data);
     })
     Event.remove("A",fn1);
     Event.trigger("A","猴赛雷啊");
    </script>
    <script>
     var a=(function(){
     var count=0;
     var btn=document.getElementById('count');
     btn.onclick=function () {
     Event.trigger('add',count++);
     }
     })();
     var b=(function () {
     var p=document.getElementById('show');
     Event.listen('add',function(data){
     p.innerHTML=data;
     })
     })();
    </script>
    </body>
    </html>
  • 最后作者也交代了发布订阅模式的不利之处:
    模块之间如果用了太多的全局发布—订阅模式来通信,那么模块与模块之间的联系就被隐藏到了背后。我们最终会搞不清楚消息来自哪个模块,或者消息会流向哪些模块,这又会给我们的维护带来一些麻烦,也许某个模块的作用就是暴露一些接口给其他模块调用。

    文档

    js发布订阅者模式详细的个人理解

    js发布订阅者模式详细的个人理解:先摘抄一下javascript设计模式与开发实践一书中的文字介绍//现实中的发布订阅模式 小明最近看上了一套房子,到了售楼处之后才被告知,该楼盘的房子早已售罄。好在售楼MM告诉小明,不久后还有一些尾盘推出,开发商正在办理相关手续,手续办好后便可以购买。
    推荐度:
    标签: 模式 发布 js
    • 热门焦点

    最新推荐

    猜你喜欢

    热门推荐

    专题
    Top