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实现仿新浪微博浮动的消息提示框(可智能定位)
Oct 10 Javascript
JS生成某个范围的随机数【四种情况详解】
Apr 20 Javascript
JavaScript接口的实现三种方式(推荐)
Jun 14 Javascript
jQuery实现简洁的轮播图效果实例
Sep 07 Javascript
原生JS简单实现ajax的方法示例
Nov 29 Javascript
jQuery实现圣诞节礼物动画案例解析
Dec 25 Javascript
react性能优化达到最大化的方法 immutable.js使用的必要性
Mar 09 Javascript
JavaScript实现的简单Tab点击切换功能示例
Jul 06 Javascript
Element实现表格分页数据选择+全选所有完善批量操作
Jun 07 Javascript
node.js事件轮询机制原理知识点
Dec 22 Javascript
JavaScript 常见的继承方式汇总
Sep 17 Javascript
vant picker+popup 自定义三级联动案例
Nov 04 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
PHP面向对象法则
2012/02/23 PHP
php封装的mongodb操作类代码
2017/08/06 PHP
页面只有一个text的时候,回车自动submit的解决方法
2010/08/12 Javascript
初学Jquery插件制作 在SageCRM的查询屏幕隐藏部分行的功能
2011/12/26 Javascript
jQuery判断iframe中元素是否存在的方法
2013/05/11 Javascript
Javascript中克隆一个数组的实现代码
2013/12/06 Javascript
jQuery固定元素插件scrolltofixed使用指南
2015/04/21 Javascript
JavaScript学习笔记之数组随机排序
2016/03/23 Javascript
JS Ajax请求如何防止重复提交
2016/06/13 Javascript
HTML中setCapture、releaseCapture 使用方法浅析
2016/09/25 Javascript
使用BootStrap进行轮播图的制作
2017/01/06 Javascript
JS实现css hover操作的方法示例
2017/04/07 Javascript
JS使用tofixed与round处理数据四舍五入的区别
2017/10/25 Javascript
iconfont的三种使用方式详解
2018/08/05 Javascript
JS中数据结构之栈
2019/01/01 Javascript
原生js实现each方法实例代码详解
2019/05/27 Javascript
node.js express框架简介与实现
2019/07/23 Javascript
jQuery使用hide()、toggle()函数实现相机品牌展示隐藏功能
2021/01/29 jQuery
[02:03]DOTA2亚洲邀请赛 HGT战队出场宣传片
2015/02/07 DOTA
[56:29]Secret vs Optic 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
python中argparse模块用法实例详解
2015/06/03 Python
Windows下的Python 3.6.1的下载与安装图文详解(适合32位和64位)
2018/02/21 Python
使用Python微信库itchat获得好友和群组已撤回的消息
2018/06/24 Python
python实现多张图片拼接成大图
2019/01/15 Python
python 计算方位角实例(根据两点的坐标计算)
2020/01/17 Python
pycharm的python_stubs问题
2020/04/08 Python
python UIAutomator2使用超详细教程
2021/02/19 Python
HTML5 CSS3新的WEB标准和浏览器支持
2009/07/16 HTML / CSS
保安的辞职报告怎么写
2014/01/20 职场文书
阿德的梦教学反思
2014/02/06 职场文书
党的群众路线教育实践活动对照检查材料
2014/09/22 职场文书
云台山导游词
2015/02/03 职场文书
个人党性分析总结
2015/03/05 职场文书
昆虫记读书笔记
2015/06/26 职场文书
学校扫黄打非工作总结
2015/10/15 职场文书
mysql事务对效率的影响分析总结
2021/10/24 MySQL