javascript观察者模式

观察者模式又叫发布-订阅模式,它定义对象间的一对多的依赖关系,当一个对象的状态发生该变时,所有依赖于它的对象都将得到通知。在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 false;
                    }
                    for(var i=0,fn; fn=fns[i++]){
                            fn.apply(this, arguments);
                    }
            },

remove:function(key,fn){ //删除订阅
                      var fns = this.clientList[key];
                      if(!fns){ //如果key对应的消息没有被人订阅,则直接返回
                            return false;
                      }
                      if(!fn){ //如果没有传入具体的回调函数,表示需要取消key对应消息的所有订阅
                           fns && (fns.length = 0);
                      }else{
                           for(var l=fns.length-1; l>=0; l--){ //反向遍历订阅的回调函数列表
                                var _fn = fns[l];
                                if(_fn ===fn){
                                      fns.splice(l,1); //删除订阅者的回调函数
                                }
                           }
                       }
            }
     };

var installEvent = function(obj){ //给所有对象动态安装发布-订阅功能
          for(var i in event){
               obj[i] = event[i];
          }
      };

var salesOffices = {}; //定义售楼处
      installEvent(salesOffices);

salesOffices.listen(‘squareMeter100‘,function(price){ // 张三订阅消息
            console.log(‘价格=‘ + price);
      });

salesOffices.listen(‘squareMeter150‘,function(price){ // 李四订阅消息
            console.log(‘价格=‘ + price);
      });

salesOffices.trigger(‘squareMeter100‘,2000000); // 输出 2000000
      salesOffices.trigger(‘squareMeter150‘,3000000); // 输出 3000000

上面的代码还存在两个小问题:
           1.每个发布者对象都添加了listen和trigger方法,以及一个缓存列表clientList,这是一种资源浪费
           2.订阅者跟售楼处对象存在一定的耦合性,订阅者至少要知道售楼处对象的名字是salesOffices,才能订阅到事件

下面是对以上两个问题的改良:

var event = {
           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),
                fns = clientList[key];
                if(!fns || fns.length == 0){ //没有绑定对应的消息
                    return false;
                }
                for(var i=0,fn; fn=fns[i++]){
                     fn.apply(this, arguments);
                }
           };

remove = function(key,fn){ //删除订阅
                   var fns = clientList[key];
                   if(!fns){ //如果key对应的消息没有被人订阅,则直接返回
                        return false;
                   }
                   if(!fn){ //如果没有传入具体的回调函数,表示需要取消key对应消息的所有订阅
                       fns && (fns.length = 0);
                   }else{
                       for(var l=fns.length-1; l>=0; l--){ //反向遍历订阅的回调函数列表
                            var _fn = fns[l];
                            if(_fn ===fn){
                                   fns.splice(l,1); //删除订阅者的回调函数
                            }
                       }
                  }
             };

return {
                   listen:listen,
                   trigger:trigger,
                   remove:remove
            };
     };

Event.listen(‘squareMeter150‘,function(price){ // 李四订阅消息
              console.log(‘价格=‘ + price);
     });

Event.trigger(‘squareMeter150‘,2000000); // 输出 2000000

改良后,发布-订阅模式可以用一个全局的Event对象来实现,订阅者不需要了解消息来自哪个发布者,发布者也不需要了解消息会推送给哪些订阅者,Event作为类似“中介者”的角色,把订阅者和发布者联系起来。

观察者模式的优点非常明显,一为时间上的解耦,二为对象间的解耦。它的应用非常广泛,既可以用在异步编程中,也可以用来编写更松耦合的代码编写。但也不是没有缺点。创建订阅者本身要消耗一定的时间和内存,而且当你订阅一个消息后,也许此消息始终都没发生,但这个订阅者会始终存在于内存中。另外,观察者模式虽然可以弱化对象间的联系,但如果过度使用的话,对象间的必要联系也将被深藏在背后,会导致程序难以跟踪维护和理解。特别是有多个发布者和订阅者嵌套到一起的时候,要跟踪一个bug不是键轻松的事。

时间: 2024-08-03 03:53:15

javascript观察者模式的相关文章

理解javascript观察者模式(订阅者与发布者)

什么是观察者模式? 观察者模式又叫做发布订阅模式,它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生改变时就会通知所有观察着对象.它是由两类对象组成,主题和观察者,主题负责发布事件,同时观察者通过订阅这些事件来观察该主体,发布者和订阅者是完全解耦的,彼此不知道对方的存在,两者仅仅共享一个自定义事件的名称. 理解观察者模式: JS传统事件就是一个观察者模式,之所以要有观察者模式,是因为有时候和传统事件无关的事件,比如:2个或者更多模块的直接通信问题,比如说我有

JavaScript实现的发布/订阅(Pub/Sub)模式

JavaScript实现的发布/订阅(Pub/Sub)模式时间 2016-05-02 18:47:58  GiantMing's blog原文  http://giantming.net/javascriptshi-xian-de-fa-bu-ding-yue-pub-sub-mo-shi/主题 JavaScript 观察者模式前段时间看了一下发布订阅者模式(也叫观察者模式),今天看<基于mvc的JavaScript的富应用开发>又看到了它,这个设计模式是非常有用的,正好写篇博客来分享一下.(

css3动画由浅入深总结

回到顶部 一:过渡动画---Transitions 一:过渡动画---Transitions 含义:在css3中,Transitions功能通过将元素的某个属性从一个属性值在指定的时间内平滑过渡到另一个属性值来实现动画功能. Transitions属性的使用方法如下所示: transition: property | duration  | timing-function | delay transition-property: 表示对那个属性进行平滑过渡. transition-duratio

司徒正美文章列表

由于本人对司徒正美文章的喜欢,特此整理文章列表如下. 一个带完整的RBAC授权系统的rails应用(第一部分)(司徒正美, 3年前, 12/6549) 一个带完整的RBAC授权系统的rails应用(第二部分)(司徒正美, 3年前, 1/1135) 随机生成十六进制颜色(司徒正美, 3年前, 0/340) ruby中的类变量与实例变量(司徒正美, 3年前, 0/231) ruby模拟多个构造器(司徒正美, 3年前, 0/153) ruby的实例方法(写方法,读方法与读写方法)(司徒正美, 3年前,

observeMode

<!DOCTYPE html><html> <head> <meta charset="utf-8"> <title></title> <script src="../jquery/jquery-1.8.0.min.js"></script> <script type="text/javascript"> //观察者模式:对程序中某一个对象

观察者模式——JavaScript

观察者模式又被称为发布-订阅模型或消息机制. 基本思想是观察者一个静态(或全局)对象,为大家提供三个方法:发布.订阅.取消订阅.想得到消息的订阅者需要通过订阅某些消息,当发布者发布某些消息的时候对应的订阅者就收到消息了.订阅者也可以取消订阅. 1 var Observer = (function(){ 2 var _messages = {}; 3 return { 4 regist: function(type,fn) { //订阅消息 5 if(typeof _messages[type]

《javascript 设计模式》 第15章 观察者模式 -- 学习笔记

定义: 在事件驱动的环境中,比如浏览器这种持续寻求用户关注的环境中,观察者模式(又名发布者-订阅者 “publisher-subscriber" 模式) 是一种管理人与其任务之间的关系(确切的讲,是其对象及其行为和状态之间的关系 )的得力工具.用javascript的 话来说,这种模式的实质 就是你可以程序中某个对象的状态进行观察并且在其发生改变时能够得到通知. 观察者API: var Publisher=function(){ this.subscribers=[]; } //推送方法 Pub

【读书笔记】读《JavaScript设计模式》之观察者模式

一.定义 在事件驱动的环境中,比如浏览器这种持续寻求用户关注的环境中,观察者模式(又名发布者-订阅者(publisher-subscripber)模式)是一种管理人与其任务之间的关系(确切地讲,是对象及其行为和状态之间的关系)的得力工具.用JavaScript的话来说,这种模式的实质就是你可以对程序中某个对象的状态进行观察,并且在其发生改变时能够得到通知. 二.例子 我们需要一个发布者的构造函数,它为该实例定义了一个类型为数组的属性,用来保存订阅者的引用. function Publisher(

《JavaScript设计模式与开发实践》读书笔记之观察者模式

1.<JavaScript设计模式与开发实践>读书笔记之观察者模式 观察者模式定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知. JavaScript中通常采用事件模型替代传统的观察者模式 1.1 逐步实现观察者模式 以客户看房为例 首先指定谁充当发布者,如售楼处 然后给发布者添加一个缓存列表,用于存放回调函数以便通知订阅者.这里为了让订阅者只接收自己感兴趣的消息,增加一个标识key 最后发布消息时候,发布者遍历缓存列表,依次触发里面存放的订阅者的回