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 相关文章推荐
关于实现代码语法标亮 dp.SyntaxHighlighter
Feb 02 Javascript
一些Javascript的IE和Firefox(火狐)兼容性的问题总结及常用例子
May 21 Javascript
jquery.simple.tree插件 更简单,兼容性更好的无限树插件
Sep 03 Javascript
javascript权威指南 学习笔记之变量作用域分享
Sep 28 Javascript
struts2+jquery+json实现异步加载数据(自写)
Jun 24 Javascript
jquery仿QQ商城带左右按钮控制焦点图片切换滚动效果
Jun 27 Javascript
AngularJS实现自定义指令与控制器数据交互的方法示例
Jun 19 Javascript
(模仿京东用户注册)用JQuery实现简单表单验证,初学者必看
Jan 08 jQuery
bootstrap+jquery项目引入文件报错的解决方法
Jan 22 jQuery
基于iScroll实现内容滚动效果
Mar 21 Javascript
vue-router 源码之实现一个简单的 vue-router
Jul 02 Javascript
js中的数组对象排序分析
Dec 11 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
使用 MySQL 开始 PHP 会话
2006/12/21 PHP
php.ini 配置文件的深入解析
2013/06/17 PHP
php cli模式下获取参数的方法
2017/05/05 PHP
PHP示例演示发送邮件给某个邮箱
2019/04/03 PHP
Gambit vs CL BO3 第二场 2.13
2021/03/10 DOTA
js如何判断用户是在PC端和还是移动端访问
2014/04/24 Javascript
教你用AngularJS框架一行JS代码实现控件验证效果
2014/06/23 Javascript
JavaScript字符串对象toLowerCase方法入门实例(用于把字母转换为小写)
2014/10/17 Javascript
深入理解JavaScript系列(33):设计模式之策略模式详解
2015/03/03 Javascript
jQuery Ajax使用FormData上传文件和其他数据后端web.py获取
2017/06/11 jQuery
Angularjs过滤器实现动态搜索与排序功能示例
2017/12/13 Javascript
微信小程序之多文件下载的简单封装示例
2018/01/29 Javascript
Nodejs实现用户注册功能
2019/04/14 NodeJs
Ajax请求时无法重定向的问题解决代码详解
2019/06/21 Javascript
手写Vue2.0 数据劫持的示例
2021/03/04 Vue.js
python分割和拼接字符串
2013/11/01 Python
centos系统升级python 2.7.3
2014/07/03 Python
Python安装官方whl包和tar.gz包的方法(推荐)
2017/06/04 Python
Python 获取当前所在目录的方法详解
2017/08/02 Python
python  Django中的apps.py的目的是什么
2018/10/15 Python
使用python获取(宜宾市地震信息)地震信息
2019/06/20 Python
Python PyQt5 Pycharm 环境搭建及配置详解(图文教程)
2019/07/16 Python
pycharm修改file type方式
2019/11/19 Python
python科学计算之narray对象用法
2019/11/25 Python
pytorch 常用线性函数详解
2020/01/15 Python
python中resample函数实现重采样和降采样代码
2020/02/25 Python
python 写函数在一定条件下需要调用自身时的写法说明
2020/06/01 Python
python3爬虫中多线程的优势总结
2020/11/24 Python
英国男女豪华配饰和礼品网站:Black.co.uk
2020/02/28 全球购物
公司员工的自我评价范例
2013/11/01 职场文书
基层干部群众路线教育实践活动个人对照检查材料
2014/09/23 职场文书
致运动员赞词
2015/07/22 职场文书
新员工入职感想
2015/08/07 职场文书
小学数学国培研修日志
2015/11/13 职场文书
原来实习报告是这样写的呀!
2019/07/03 职场文书
python中requests库+xpath+lxml简单使用
2021/04/29 Python