• Javascript设计模式之观察者模式


    首先说一下观察者模式的应用场景

    观察者的使用场合就是:当一个对象的改变需要同时改变其它对象,并且它不知道具体有多少对象需要改变的时候,就应该考虑使用观察者模式。(Tom大叔)

    具体说一下这个观察者模式,就是一个发报纸的过程。我们订阅了报纸,在报社的数组里加上我们的名字(不仅是名字了是一个带我们名字的处理函数),这是订阅事件;报社才不管你订没订报纸,他只管给他数组里的人发报纸;我们在编码的时候只监听发报纸的事件,订不订报纸,谁订报纸,都是你的事,就不在放在监听的事件里了,于是就有了减少监听的优化;

    我们来构建一下观察者API

    首先我们设置一个报社:

    1 function Publisher(){
    2   this.subscribers = [];//报社存放关于订阅者的数组
    3 }

    下面实现报社发报纸:

    1 Publisher.prototype.deliver = function(data) {//记住哦,发报纸是deliver方法,里面是报纸内容的参数
    2   this.subscribers.forEach(function(fn){
    3     fn(data);
    4   })
    5   return this;
    6 };

    好,下面是订阅方法,当然,所有人想订阅就订阅,方法加在Function的原型链上:

    Function.prototype.subscribe = function(publisher){
      var this = that;
      var alreadyExists = publisher.subscribers.some(function(el){
        return el === that;
      });
      if ( !alreadyExists) {
        publisher.subscribers.push(this);
      };
      return this;
    }

    数组的some方法,和foreach的回调形式差不多,不过只要有一次调用回调函数就会返回true否则为false;

    退订方法:

    Function.prototype.unsubscribe = function(publisher){
      var this = that;
      publisher.subscribers = publisher.subscribers.filter(function(el){
        return el !== that;
      })
      return this;
    }

    这里数组的filter方法,返回符合条件的数组,遍历数组,如果他的某一元素不等于这“我”,就返回其他。相当于数组的shift(“我”)方法;

    至此API完了。这玩意怎么用呢。

    举一个动画的例子;

    var Animation = function(o){
      this.onStart = new Publisher,
      this.onComplete = new Publisher,
      this.onTween = new Publisher;
     };
    Animation.prototype.fly = funciton(){
      this.onStart.deliver();
      for(...){//这里遍历所有的组织
        this.onTween.deliver(i);
      }
      this.onComplete.deliver();
    } 
    var Superman = new Animation({})//设置特性
    var pushOnCape = function(i){};//这里添加处理事件
    var takeOfCape = function(i){};//这里添加处理事件
    pushOnCape.subscribe(Superman.onStart);
    takeOfCape.subscribe(Superman.onComplete);
    //然后,这个fly写哪都行
    $('div').addEventListener('click',function(){
      Superman.fly();
    })

    说明:

    这里监听一个click,让报社发报纸。发给谁用谁订阅。比如pushOnCape、和takeOfCape都

    调用了subscribe方法,加入一个事件就让他订阅就行;

    这里的subscribe方法传递一个onStart相当于start报社,还有另外两家报社,他们分别发自己的报纸,想订谁的

    报纸就订阅哪家的报社;

    当点击div的时候。调用了fly方法,各个报社开始发自己的报纸(deliver),报社查看自己的订阅者数组[],发现

     pushOnCape、takeOfCape调用过subscribe方法,加入到数组了,就给他发消息了;消息是data,这里没啥用,不过

     this.onTween.deliver(i);这里可以区分i,主要是发送消息到他自己,这里是pushOnCape、takeOfCape,于是调用它们自己的函数

     function(i){}如注释,->这里添加处理事件,其实是触发click的时候各个部分进行的动作;

    总结一下:

    观察者模式的作用就是将各种行为和信息都给他的自己,用subscribe方法来做,削减监听器的数量,减低内存消耗,

    提高互动性能;

    它的坏处就是创建可观察对象带来的时间消耗,不过你可以在用它的时候再实例化它,程序初始化的时候就不会有影响;

    首先说一下观察者模式的应用场景

    观察者的使用场合就是:当一个对象的改变需要同时改变其它对象,并且它不知道具体有多少对象需要改变的时候,就应该考虑使用观察者模式。(Tom大叔)

    具体说一下这个观察者模式,就是一个发报纸的过程。我们订阅了报纸,在报社的数组里加上我们的名字(不仅是名字了是一个带我们名字的处理函数),这是订阅事件;报社才不管你订没订报纸,他只管给他数组里的人发报纸;我们在编码的时候只监听发报纸的事件,订不订报纸,谁订报纸,都是你的事,就不在放在监听的事件里了,于是就有了减少监听的优化;

    我们来构建一下观察者API

    首先我们设置一个报社:

    function Publisher(){

    this.subscribers = [];//报社存放关于订阅者的数组

    }

    下面实现报社发报纸:

    Publisher.prototype.deliver = function(data) {//记住哦,发报纸是deliver方法,里面是报纸内容的参数

    this.subscribers.forEach(function(fn){

    fn(data);

    })

    return this;

    };

    给基础不好的同学讲一下,forEach传递两个参数得时候第一个参数是数组内容,第二个参数是index,这里的fn是

    代表数组里“我”的处理;我还为怎么传进来fn纠结了一阵,是被匿名函数蒙蔽了双眼;返回this,让他能够连续调用,能

    连续不断的投送数据;

    好,下面是订阅方法,当然,所有人想订阅就订阅,方法加在Function的原型链上:

    Function.prototype.subscribe = function(publisher){

    var this = that;

    var alreadyExists = publisher.subscribers.some(function(el){

    return el === that;

    });

    if ( !alreadyExists) {

    publisher.subscribers.push(this);

    };

    return this;

    }

    数组的some方法,和foreach的回调形式差不多,不过只要有一次调用回调函数就会返回true否则为false;

    退订方法:

    Function.prototype.unsubscribe = function(publisher){

    var this = that;

    publisher.subscribers = publisher.subscribers.filter(function(el){

    return el !== that;

    })

    return this;

    }

    这里数组的filter方法,返回符合条件的数组,遍历数组,如果他的某一元素不等于这“我”,就返回其他。相当于数组的shift(“我”)方法;

    至此API完了。这玩意怎么用呢。

    举一个动画的例子;

    var Animation = function(o){

    this.onStart = new Publisher,

    this.onComplete = new Publisher,

    this.onTween = new Publisher;

    };

    Animation.prototype.fly = funciton(){

    this.onStart.deliver();

    for(...){//这里遍历所有的组织

    this.onTween.deliver(i);

    }

    this.onComplete.deliver();

    var Superman = new Animation({})//设置特性

    var pushOnCape = function(i){};//这里添加处理事件

    var takeOfCape = function(i){};//这里添加处理事件

    pushOnCape.subscribe(Superman.onStart);

    takeOfCape.subscribe(Superman.onComplete);

    然后,这个fly写哪都行

    $('div').addEventListener('click',function(){

    Superman.fly();

    })

    说明:

    这里监听一个click,让报社发报纸。发给谁用谁订阅。比如pushOnCape、和takeOfCape都

    调用了subscribe方法,加入一个事件就让他订阅就行;

    这里的subscribe方法传递一个onStart相当于start报社,还有另外两家报社,他们分别发自己的报纸,想订谁的

    报纸就订阅哪家的报社;

    当点击div的时候。调用了fly方法,各个报社开始发自己的报纸(deliver),报社查看自己的订阅者数组[],发现

     pushOnCape、takeOfCape调用过subscribe方法,加入到数组了,就给他发消息了;消息是data,这里没啥用,不过

     this.onTween.deliver(i);这里可以区分i,主要是发送消息到他自己,这里是pushOnCape、takeOfCape,于是调用它们自己的函数

     function(i){}如注释,->这里添加处理事件,其实是触发click的时候各个部分进行的动作;

    总结一下:

    观察者模式的作用就是将各种行为和信息都给他的自己,用subscribe方法来做,削减监听器的数量,减低内存消耗,

    提高互动性能;

    它的坏处就是创建可观察对象带来的时间消耗,不过你可以在用它的时候再实例化它,程序初始化的时候就不会有影响;

  • 相关阅读:
    [CF846E]Chemistry in Berland题解
    [CF846D]Monitor题解
    [CF846B]Math Show题解
    [CF846A]Curriculum Vitae题解
    斜率优化 学习笔记
    【CF115E】Linear Kingdom Races 题解(线段树优化DP)
    【洛谷P3802】小魔女帕琪 题解(概率期望)
    7月13日考试 题解(DFS序+期望+线段树优化建图)
    【BZOJ1426】收集邮票 题解 (期望)
    【HNOI2010】弹飞绵羊 题解(分块)
  • 原文地址:https://www.cnblogs.com/dh-dh/p/4998872.html
Copyright © 2020-2023  润新知