浅谈javasript 观察者模式

原创 2012年03月30日 14:19:48
对于密集型前端项目而言,业务的复杂程度会导致代码的耦合非常巨大,如何解耦和更加优雅的实现成为每个前端开发工程师的一个追求的目标。前端MVC,观察者模式,面向接口编程等等方案的提出都为我们解决了一些项目中常常碰到的实际问题。
之前winter大大吐槽过javascript 乱用设计模式的方式,我想观察者模式应用在相对独立的模块之间的解耦不属于此列。加上阿当也在他的微博上说到,会不会使用js的消息通知机制,可以区分js的老手和新手之分。由此可见观察者模式对于一些实际开发者而言还是比较讨好的。
那么具体什么是观察者模式,用通俗易懂的话说,就是模块之间的订阅以及广播。假设有A、B两个模块,相互不知道对方的存在(相互独立),B模块订阅了A模块的通知,这个假如时候A 由于状态的改变会发出广播,那么对模块A 订阅了这个状态的B就执行相应的逻辑。 整个订阅和通知的这个机制始终处于第三方,相当于一个接线员的工作,很像一个观察者,就是所谓的观察者模式。在wiki上有更加详细的解释,感兴趣的同学可以看看
[url=http://zh.wikipedia.org/wiki/%E8%A7%82%E5%AF%9F%E8%80%85%E6%A8%A1%E5%BC%8F]观察者模式wiki[/url]
这里引用wiki上的对观察者模式的用途阐述:

  • 当抽象个体有两个相互依赖的层面时,封装这些层面在单独的物件内可将允许程序设计师单独地去变更重复使用这些物件,而不会产生两者之间的交互的问题。
  • 当其中一个物件的变更会影响其他物件,却又不知道多少物件必须被同时变更时。
  • 当物件应该有能力通知其他物件,又不应该知道其他物件的实际细节时
上面提到的观察者用途是否似曾相识?工作中的实际项目是否常见呢?我觉得答案是肯定的,除非你的业务逻辑不需要和任何外界的模块交互。举个很简单的例子来说。目前很流行的SNS站点,大多都有发消息的功能,无论是心情也好,微博也好就拿微博举例子吧。在发消息这个动作进行的过程需要做什么事情?
消息发送成功之后通知主页timeline立马显示那条消息,在自己的发的消息数字上+1,甚至在一些SAP(single page app上)还需要更新我发送的消息 timeline 等等。
同样微博的收听,评论等等功能也一样。
比较耦合的写法就是在发送请求成功过后,依次在callback里执行相应的逻辑。这就使得,发消息的模块,必须要知道他发送成功了必须要通知哪几个模块,并且执行他们的逻辑。
而在观察者模式情况下是怎么做的呢?抽象的说,在发送消息的请求成功返回后,发送广播消息已发送成功,所有订阅了这个类型的广播的模块依次自己去执行自己的对应逻辑。这样每个模块只需要面向和自己有关的广播,处理相应的逻辑。而不用关心自己和其他具体模块交互的逻辑。
那么到底如何实现这个观察者模式呢?
其实在我们理解里以后,发现观察者需要提供的最基本的接口有下面三个:
  1. subscribe 订阅
  2. fire 发送广播
  3. unsubscribe 取消订阅


var observer = (function(){
     var obList = {};
     function subscribe(msgType,callback){
          //订阅广播
          if(!obList[msgType]){
               obList[msgType] = []
          }
          obList[massageType].push(callback);
     }
     function fire(msgType,callback, data){
          //发送广播
          if(obList[msgType]){
               for(var i=0,l=obList[msgType].length;i<l;i++){
                    //发送广播的数据data
                    obList[msgType][i](data);
               }
          }
     }
     function unsubscribe(msgType, callback){
          //取消订阅
          if(obList[msgType]){
               obList[msgType].shift(obList[msgType].indexOf(callback));
          }         
     }
     return {
         'subscribe' : subscribe,
         'fire' : fire,
         'unsubscribe' : unsubscribe
     };
})()
以上代码是为了阐述观察者模式随手写的单例,不推荐直接使用,我甚至都没有自测,只是把实现的大概思想在这里用代码表述了一遍。当然要注意的是,观察者模式如果管理不善的话,也会导致消息类型的以上的msgType的肆意增长,要优雅的使用观察者模式还需要更好的管理这些msgType,或者可以根据观察的对象不同定义一些不同的频道,这样使得即便观察对象多了也便于维护。
使用观察者模式的好处是你只需要通过这样的设计,就可以避免代码里大量的耦合,做到充分解耦,何乐而不为呢?加上现在DOM LEVEL3 event对象也开始支持以前不支持的但却被很多人实现了的customEvent。通过这个方式也可以实现观察者模式,只不过这个方式依赖DOM和事件对象,或是对于过于抽象的组件也许不适合。其实事件监听器(EventListener)也是观察者模式的一种,现实的例子中观察者模式还是很流行的,所以了解这个模式对前端开发来说很有帮助。

观察者模式的浅析

观察者模式的浅析 简单地说,观察者模式定义了一个一对多的依赖关系,让一个或多个观察者对象监察一个主题对象。这样一个主题对象在状态上的变化能够通知所有的依赖于此对象的那些观察者对象,使...
  • Lucky_bo
  • Lucky_bo
  • 2016年06月29日 17:34
  • 694

浅谈为什么设计模式要有观察者模式--观察者模式的意义

设计模式可以说是一种代码规范,也可以说是一种前人总结的奇技淫巧,对于后来编程者,学习设计模式可以对编程思路有一些启发,其中也包括经验启发. php相对java形式比较随意,所以对于模式设计更需要多花时...
  • h330531987
  • h330531987
  • 2017年09月03日 14:23
  • 381

浅谈JavaSript模块化规范

模块化是指在解决某一个复杂问题或者一系列的杂糅问题时,依照一种分类的思维把问题进行系统性的分解以之处理。模块化是一种处理复杂系统分解为代码结构更合理,可维护性更高的可管理的模块的方式。可以想象一个巨大...
  • iongzhidun1
  • iongzhidun1
  • 2015年05月20日 14:20
  • 239

好记性不如烂笔头之常用javasript基础

好记性不如烂笔头之常用javasript基础
  • sunmun
  • sunmun
  • 2016年07月14日 13:07
  • 808

javasript学习之一(函数)

函数 概述 函数调用 函数调用模式 方法调用模式 构造器调用模式 使用apply和call调用函数概述 函数表达式的最后有一个圆括号,表示这个函数被调用 圆括号中任何被传入的变量,都会被翻译...
  • fibonacii
  • fibonacii
  • 2016年11月27日 00:57
  • 135

观察者模式浅谈

什么是观察者模式?观察者(Observer)模式又名发布-订阅(Publish/Subscribe)模式。 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知...
  • u012233285
  • u012233285
  • 2016年10月29日 21:42
  • 99

浅谈观察者模式

观察者模式(有时又被称为发布-订阅模式、模型-视图模式、源-收听者模式或从属者模式)软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这...
  • amkil
  • amkil
  • 2015年04月19日 12:19
  • 212

javascript:;与javascript:void(0)使用介绍

有时候我们在编写js过程中,需要触发事件而不需要返回值,那么就可能需要这样的写法 href=”#”,包含了一个位置信息.默认的锚是#top,也就是网页的上端,当连续快速点击此链接时会导致浏览器巨慢甚...
  • m631521383
  • m631521383
  • 2014年12月09日 10:23
  • 1334

一个用观察者模式解决实际问题的例子

前几天组里接到一个以前开发的已上线项目的维护任务,要求把其中的一些数据定时通过webservice接口上传到当地某市某平台上面,基本上算是个体力活儿了。 时间仓促只好加班加点,搜集比对 -->拼写S...
  • u012763117
  • u012763117
  • 2014年03月09日 02:31
  • 1485

javasript处理字符串问题集

1带中文的字符串的长度问题http://nio.infor96.com/archives/182 在 JavaScript 编程中,经常需要对提交的表单进行验证,特别是对用户在文本框中输入的字符串的长...
  • yethyeth
  • yethyeth
  • 2007年09月18日 15:26
  • 1085
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:浅谈javasript 观察者模式
举报原因:
原因补充:

(最多只允许输入30个字)