JavaScript设计模式之观察者模式(发布者-订阅者模式)


Posted in Javascript onSeptember 24, 2014

观察者模式( 又叫发布者-订阅者模式 )应该是最常用的模式之一. 在很多语言里都得到大量应用. 包括我们平时接触的dom事件. 也是js和dom之间实现的一种观察者模式.

div.onclick  =  function click (){

alert ( ”click' )

}

只要订阅了div的click事件. 当点击div的时候, function click就会被触发。

那么到底什么是观察者模式呢. 先看看生活中的观察者模式。

好莱坞有句名言. “不要给我打电话, 我会给你打电话”. 这句话就解释了一个观察者模式的来龙去脉。 其中“我”是发布者, “你”是订阅者。

再举个例子,我来公司面试的时候,完事之后每个面试官都会对我说:“请留下你的联系方式, 有消息我们会通知你”。 在这里“我”是订阅者, 面试官是发布者。所以我不用每天或者每小时都去询问面试结果, 通讯的主动权掌握在了面试官手上。而我只需要提供一个联系方式。

观察者模式可以很好的实现2个模块之间的解耦。 假如我正在一个团队里开发一个html5游戏. 当游戏开始的时候,需要加载一些图片素材。加载好这些图片之后开始才执行游戏逻辑. 假设这是一个需要多人合作的项目. 我完成了Gamer和Map模块, 而我的同事A写了一个图片加载器loadImage。

loadImage的代码如下:

loadImage(  imgAry,  function(){

Map.init();

Gamer.init();

} )

当图片加载好之后, 再渲染地图, 执行游戏逻辑. 嗯, 这个程序运行良好. 突然有一天, 我想起应该给游戏加上声音功能. 我应该让图片加载器添上一行代码.
loadImage(  imgAry,  function(){

Map.init();

Gamer.init();

Sount.init();

} )

可是写这个模块的同事A去了外地旅游. 于是我打电话给他, 喂. 你的loadImage函数在哪, 我能不能改一下, 改了之后有没有副作用. 如你所想, 各种不淡定的事发生了. 如果当初我们能这样写呢:
loadImage.listen( ”ready', function(){

Map.init();

})

loadImage.listen( ”ready', function(){

Gamer.init();

})

loadImage.listen( ”ready', function(){

Sount.init();

})

loadImage完成之后, 它根本不关心将来会发生什么, 因为它的工作已经完成了. 接下来它只要发布一个信号.

loadImage.trigger( ”ready' );

那么监听了loadImage的'ready'事件的对象都会收到通知. 就像上个面试的例子. 面试官根本不关心面试者们收到面试结果后会去哪吃饭. 他只负责把面试者的简历搜集到一起. 当面试结果出来时照着简历上的电话挨个通知.

说了这么多概念, 来一个具体的实现. 实现过程其实很简单. 面试者把简历扔到一个盒子里, 然后面试官在合适的时机拿着盒子里的简历挨个打电话通知结果.

Events = function() {

var listen, log, obj, one, remove, trigger, __this;

obj = {};

__this = this;

listen = function( key, eventfn ) {  //把简历扔盒子, key就是联系方式.

var stack, _ref;  //stack是盒子

stack = ( _ref = obj[key] ) != null ? _ref : obj[ key ] = [];

return stack.push( eventfn );

};

one = function( key, eventfn ) {

remove( key );

return listen( key, eventfn );

};

remove = function( key ) {

var _ref;

return ( _ref = obj[key] ) != null ? _ref.length = 0 : void 0;

};

trigger = function() {  //面试官打电话通知面试者

var fn, stack, _i, _len, _ref, key;

key = Array.prototype.shift.call( arguments );

stack = ( _ref = obj[ key ] ) != null ? _ref : obj[ key ] = [];

for ( _i = 0, _len = stack.length; _i < _len; _i++ ) {

fn = stack[ _i ];

if ( fn.apply( __this,  arguments ) === false) {

return false;

}

}

return {

listen: listen,

one: one,

remove: remove,

trigger: trigger

}

}

最后用观察者模式来做一个成人电视台的小应用.

//订阅者

var adultTv = Event();

adultTv .listen(  ”play',  function( data ){

alert ( “今天是谁的电影” + data.name );

});

//发布者

adultTv .trigger(  ”play',  { ‘name': ‘麻生希' }  )
Javascript 相关文章推荐
Jquery Ajax学习实例6 向WebService发出请求,返回DataSet(XML) 异步调用
Mar 18 Javascript
变量声明时命名与变量作为对象属性时命名的区别解析
Dec 06 Javascript
深入理解Ajax的get和post请求
Jun 02 Javascript
分享jQuery网页元素拖拽插件
Dec 01 Javascript
浅析jsopn跨域请求原理及cors(跨域资源共享)的完美解决方法
Feb 06 Javascript
JS简单实现数组去重的方法示例
Mar 27 Javascript
AngularJS实现动态添加Option的方法
May 17 Javascript
js单页hash路由原理与应用实战详解
Aug 14 Javascript
浅谈Angular2 模块懒加载的方法
Oct 04 Javascript
vue-cli3 karma单元测试的实现
Jan 18 Javascript
微信小程序错误this.setData报错及解决过程
Sep 18 Javascript
基于JavaScript实现表格隔行换色
May 08 Javascript
JavaScript获取图片真实大小代码实例
Sep 24 #Javascript
再探JavaScript作用域
Sep 24 #Javascript
深入理解javascript原型链和继承
Sep 23 #Javascript
深入理解javascript构造函数和原型对象
Sep 23 #Javascript
常用的jquery模板插件——jQuery Boilerplate介绍
Sep 23 #Javascript
Javascript的setTimeout()使用闭包特性时需要注意的问题
Sep 23 #Javascript
IE6 hack for js 集锦
Sep 23 #Javascript
You might like
全国FM电台频率大全 - 9 上海市
2020/03/11 无线电
个人站长制做网页常用的php代码
2007/03/03 PHP
php计算十二星座的函数代码
2012/08/21 PHP
PHP  实现等比压缩图片尺寸和大小实例代码
2016/10/08 PHP
javascript编程起步(第七课)
2007/02/27 Javascript
JSDoc 介绍使用规范JsDoc的使用介绍
2011/02/12 Javascript
js 分页全选或反选标识实现代码
2011/08/09 Javascript
jquery插件tooltipv顶部淡入淡出效果使用示例
2013/12/05 Javascript
如何在MVC应用程序中使用Jquery
2014/11/17 Javascript
基于jQuery实现文本框只能输入数字(小数、整数)
2016/01/14 Javascript
Javascript获取随机数的实现方法
2016/06/22 Javascript
jQuery实现产品对比功能附源码下载
2016/08/09 Javascript
jquery.tableSort.js表格排序插件使用方法详解
2020/08/12 Javascript
谈谈JavaScript中super(props)的重要性
2019/02/12 Javascript
vue css 引入asstes中的图片无法显示的四种解决方法
2020/03/16 Javascript
解决vue项目中出现Invalid Host header的问题
2020/11/17 Javascript
python中django框架通过正则搜索页面上email地址的方法
2015/03/21 Python
Python中的ctime()方法使用教程
2015/05/22 Python
Python编程实现的图片识别功能示例
2017/08/03 Python
python3写爬取B站视频弹幕功能
2017/12/22 Python
python3+dlib实现人脸识别和情绪分析
2018/04/21 Python
pytorch对可变长度序列的处理方法详解
2018/12/08 Python
python通过txt文件批量安装依赖包的实现步骤
2019/08/13 Python
Python自省及反射原理实例详解
2020/07/06 Python
亚马逊印度站:Amazon.in
2017/10/15 全球购物
Bed Bath & Beyond加拿大官网:购买床上用品、浴巾、厨房电器等
2019/10/04 全球购物
是否有自动比较结构的方法
2015/06/03 面试题
Internet主要有哪些网络群组成
2015/12/24 面试题
房地产广告策划方案
2014/05/15 职场文书
电教室标语
2014/06/20 职场文书
论群众路线学习笔记
2014/11/06 职场文书
关于环保的广播稿
2015/12/17 职场文书
护士医德医风心得体会
2016/01/25 职场文书
我对PyTorch dataloader里的shuffle=True的理解
2021/05/20 Python
如何解决goland,idea全局搜索快捷键失效问题
2022/04/03 Golang
详解Nginx的超时keeplive_timeout配置步骤
2022/05/25 Servers