zoukankan      html  css  js  c++  java
  • 发布-订阅模式

    1.什么是发布订阅模式

    发布订阅模式 又叫观察者模式,他是定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变,所有依赖他的对象都将得到通知。

    在javascript开发中,我们一般用事件模型来替代传统的发布-订阅模式。

    2.Dom事件

    实际上,只要我们曾经在dom节点上绑定过事件函数,那么我们就曾经使用过发布-订阅模式。

    document.getElementById('test').addEventListener('click',function(){ alert(2)},fasle;)

    在这里需要监控用户点击行为,但是我们没。法预知用户在什么时候点击。所以我们订阅document.body上的click事件,

    当body被点击时,body便会像订阅者发布这个消息。

    3.自定义事件。

    一售楼部为例,购房者订阅售楼部消息,售楼部定时推送消息给购房者;

    首先,要制定好谁当发布者;

    然后,给发布者添加一个缓存列表,用于存放回掉函数以便通知订阅者

    最后,发布消息的时候,发布者会遍历这个缓存列表,一次触发里面的订阅者回掉信息对各自进行处理;

    var salesOffices = {}; //定义售楼处
    
    
    salesOffices.clientList = [];//缓存列表,存放订阅者的回掉
    
    salesOffices.listen = function(fn){ //增加订阅者,
      this.clientList.push(fn);//订阅的消息添加进缓存列表
    }
    
    
    salesOffices.trigger = function(){
      for (var i=0,fn;fn = this.clientList[i++];){
         fn.apply(this,arguments);//arguments 是发布消息时带上的参数 
      }    
    }
    
    
    //测试一下
    
    salesOffices.listen(function(price,squareMeter){ //小明订阅
      console.log('价格'+price);
      console.log('面积'+squareMeter);
    })
    
    salesOffices.listen(function(price,squareMeter){ //小红订阅
      console.log('价格'+price);
      console.log('面积'+squareMeter);
    })
    
    
    salesOffices.trigger(2000000,88) //输出2000000 ,88平方
    salesOffices.trigger(3000000,118) //300000,118平方

    至此,我们已经实现了一个最简单的发布-订阅模式;但是还存在一些问题,。我们看到订阅者接受到了发布者的每个消息

    虽然小明只想买88平的房子。但是发布者把118的房子也推送了,这是不必要的困扰,所以我们有必要增加一个表示key

    r让订阅者之订阅自己喜欢的消息,改写后的代码如下;

    var salesOffices = {}; //定义售楼处
    
    
    salesOffices.clientList = [];//缓存列表,存放订阅者的回掉
    
    salesOffices.listen = function(key,fn){ //增加订阅者,
        if(!this.clientList[key]){//如果还没有订阅过此类消息,给该类消息创//建一个缓存列表
        this.clientList[key] = [];
      }
      this.clientList[key].push(fn);//订阅的消息添加进缓存列表
    }
    
    
    salesOffices.trigger = function(){
      var key = Array.prototype.shift.call(arguments),//取出消息类型
            fns = this.clientList[key];
       
      if(!fns || fns.length === 0){ //如果没有订阅则返回
        return ;
      }
      for (var i=0,fn;fn = fns[i++];){
         fn.apply(this,arguments);//arguments 是发布消息时带上的参数 
      }    
    }
    
    
    //测试一下
    
    salesOffices.listen('squerMeter88',function(price){ //小明订阅
      console.log('价格='+price);
      //console.log('面积'+squareMeter);
    })
    
    salesOffices.listen('squareMeter100',function(price){ //小红订阅
      console.log('价格='+price);
     // console.log('面积'+squareMeter);
    })
    
    
    salesOffices.trigger('squareMeter88',88) //输出2000000 ,88平方
    salesOffices.trigger('squareMeter100',118) //300000,118平方 

    现在订阅者可以只订阅自己感兴趣的事件了,但是,假设又去别的售楼部,那么这段代码是否又要在另一个地方重写一次呢,

    有没有办法让所有的对象都拥有发布-订阅的功能呢?

    显然是有的,javascript 是一门解释执行的语言,给对象动态添加职责是理所当然的事情;

    所以我们把发布-订阅的功能提取出来放在一个单独的对象内;

    var event = {
    
        clientList:[],
    
        listen:function(key,fn){
            if(!this.clientList[key]){
            
                this.clientList[key] = [];
            }
            this.clientList[key].push(fn);
        },
    
        trigger:function(){
           var key = Array.prototype.shift.call(arguments),
                 fns = this.clientList[key];
    
           if(!fns|| fns.length === 0){
               return;
            }
             for(var i=0,fn;fns[i++]){
                 fn.apply(this,arguments);
             }
        }
    
    
    //在定义一个installEvent函数,这个函数可以所有对象都动态安装发布-订阅功能;
    
    var installEvent = function(obj){
      for(var i in event){
         obj[i] = event[i];
       }
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    }        
  • 相关阅读:
    博客园美化-SimpleMemor
    Java多线程-synchronized与ReentrantLock
    springboot中删除@SessionAttributes注解的属性
    SSM整合笔记
    Spring中xml和注解方式使用AOP
    Mysql 数据库基本操作
    Mysql 二进制包安装
    named piped tcp proxy 下载
    docker容器中日志文件过大处理方法
    自动做bond的脚本
  • 原文地址:https://www.cnblogs.com/vali/p/7502943.html
Copyright © 2011-2022 走看看