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 相关文章推荐
baidu博客的编辑友情链接的新的层窗口!经典~支持【FF】
Feb 09 Javascript
javascript网页关闭时提醒效果脚本
Oct 22 Javascript
javascript 打印内容方法小结
Nov 04 Javascript
JS判断当前日期是否大于某个日期的实现代码
Sep 02 Javascript
原生javascript和jquery判断浏览器版本等信息
Jul 04 Javascript
JavaScript 弹出子窗体并返回结果到父窗体的实现代码
May 28 Javascript
JS原型对象的创建方法详解
Jun 16 Javascript
微信小程序实现缓存根据不同的id来进行设置和读取缓存
Jun 12 Javascript
深入浅析JavaScript中的RegExp对象
Sep 18 Javascript
JavaScript 作用域实例分析
Oct 02 Javascript
vue项目中使用rem,在入口文件添加内容操作
Nov 11 Javascript
使用AutoJs实现微信抢红包的代码
Dec 31 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 图片上传代码
2011/09/13 PHP
php 字符串压缩方法比较示例
2014/01/23 PHP
php在数据库抽象层简单使用PDO的方法
2015/11/03 PHP
PHP+Mysql+Ajax实现淘宝客服或阿里旺旺聊天功能(前台页面)
2017/06/16 PHP
PHP使用Curl实现模拟登录及抓取数据功能示例
2018/04/27 PHP
让浏览器非阻塞加载javascript的几种方法小结
2011/04/25 Javascript
使用javascript获取flash加载的百分比的实现代码
2011/05/25 Javascript
页面调用单个swf文件,嵌套出多个方法。
2011/11/21 Javascript
JSON辅助格式化处理方法
2013/03/26 Javascript
cookie.js 加载顺序问题怎么才有效
2013/07/31 Javascript
让JavaScript的Alert弹出框失效的方法禁止弹出警告框
2014/09/03 Javascript
JavaScript获得url所有参数键值表的方法
2015/03/21 Javascript
jQuery仿淘宝网产品品牌隐藏与显示效果
2015/09/01 Javascript
javascript实现下雪效果【实例代码】
2016/05/03 Javascript
基于jQuery的Web上传插件Uploadify使用示例
2016/05/19 Javascript
前端页面文件拖拽上传模块js代码示例
2017/05/19 Javascript
详解react如何在组件中获取路由参数
2017/06/15 Javascript
详解vue mint-ui源码解析之loadmore组件
2017/10/11 Javascript
微信小程序使用request网络请求操作实例
2017/12/15 Javascript
Angular2实现的秒表及改良版示例
2019/05/10 Javascript
vue iview多张图片大图预览、缩放翻转
2019/07/13 Javascript
Element ui 下拉多选时新增一个选择所有的选项
2019/08/21 Javascript
Python常见文件操作的函数示例代码
2011/11/15 Python
Python中的MongoDB基本操作:连接、查询实例
2015/02/13 Python
Python 迭代器与生成器实例详解
2017/05/18 Python
Python3实现定时任务的四种方式
2019/06/03 Python
Python selenium模拟手动操作实现无人值守刷积分功能
2020/05/13 Python
Keras 实现加载预训练模型并冻结网络的层
2020/06/15 Python
英国名牌服装购物网站:OD’s Designer
2019/09/02 全球购物
学生检讨书
2015/01/27 职场文书
2015年三万活动总结
2015/03/25 职场文书
医院志愿者活动总结
2015/05/06 职场文书
反腐倡廉观后感
2015/06/08 职场文书
学习党史心得体会2016
2016/01/23 职场文书
教你用python控制安卓手机
2021/05/13 Python
Elasticsearch 配置详解
2022/04/19 Java/Android