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

观察者模式( 又叫发布者-订阅者模式 )应该是最常用的模式之一. 在很多语言里都得到大量应用. 包括我们平时接触的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': ‘麻生希' }  )

时间: 2014-09-21

JavaScript 设计模式之组合模式解析

怎么说呢?!就像是动物(组合对象)一样,当它生下后代(叶对象)时,它的后代就有了某种功能(比如:挖洞,听力好等等):也像是一棵树,它有一个根(组合对象)然后是从这个棵树向外冒出的其他枝杆(组合对象)以及从这些枝杆又向外长的叶子(叶对象).换句话说,就是当祖先已经有了,那么只要从这个祖先衍生出来的其他孩子(包括这个祖先下的其他组合对象)已经就具备了某种功能,看上去貌似又有些像是继承."组合模式"在组合对象的层次体系中有两种类型的对象:叶对象和组合对象.组合模式擅长于对大批对象进行操作.

JavaScript设计模式之单例模式实例

<Practical Common Lisp>的作者 Peter Seibel 曾说,如果你需要一种模式,那一定是哪里出了问题.他所说的问题是指因为语言的天生缺陷,不得不去寻求和总结一种通用的解决方案. 不管是弱类型或强类型,静态或动态语言,命令式或说明式语言.每种语言都有天生的优缺点.一个牙买加运动员, 在短跑甚至拳击方面有一些优势,在练瑜伽上就欠缺一些. 术士和暗影牧师很容易成为一个出色的辅助,而一个背着梅肯满地图飞的敌法就会略显尴尬. 换到程序中, 静态语言里可能需要花很多功夫来实现装饰

JavaScript 设计模式学习 Factory

复制代码 代码如下: /* DisplayModule interface. */ var DisplayModule = new Interface('DisplayModule', ['append', 'remove', 'clear']); /* ListDisplay class. */ //通过接口实现工厂,这是通过List方式显示RSS var ListDisplay = function(id, parent) { // implements DisplayModule this

JavaScript 设计模式 安全沙箱模式

命名空间 JavaScript本身中没有提供命名空间机制,所以为了避免不同函数.对象以及变量名对全局空间的污染,通常的做法是为你的应用程序或者库创建一个唯一的全局对象,然后将所有方法与属性添加到这个对象上. 复制代码 代码如下: /* BEFORE: 5 globals */ // constructors function Parent() {} function Child() {} // a variable var some_var = 1; // some objects var mo

JavaScript编程设计模式之构造器模式实例分析

本文实例讲述了JavaScript编程设计模式之构造器模式.分享给大家供大家参考,具体如下: 经典的OOP语言中,构造器(也叫构造函数)是一个用于初始化对象的特殊方法.在JS中,因为一切皆对象,对象构造器经常被提起. 对象构造器用于建立制定类型(Class)的对象,可以接受参数用于初始化对象的属性和方法. 对象建立 在JS中,有三个常用的方法用于建立对象: //1, 推荐使用 var newObject = {}; //2, var newObject = Object.create( null

javascript设计模式之解释器模式详解

神马是"解释器模式"? 先翻开<GOF>看看Definition:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子. 在开篇之前还是要科普几个概念: 抽象语法树: 解释器模式并未解释如何创建一个抽象语法树.它不涉及语法分析.抽象语法树可用一个表驱动的语法分析程序来完成,也可用手写的(通常为递归下降法)语法分析程序创建,或直接client提供. 解析器: 指的是把描述客户端调用要求的表达式,经过解析,形成一个抽象语法树的程序. 解

JavaScript设计模式之工厂模式和构造器模式

什么是模式 前阵子准备期末考试,劳神又伤身的,实在闲不得空来更新文章,今天和大家说说javascript中的设计模式. 首先呢,我们需要知道的是:模式是一种可复用的解决方案,而反模式呢就是针对某个问题的不良解决方案. js反模式常见例子 1.向setTimeout和setInterval传递字符串,而不是函数,这会触发eval()的内部使用. 2.在全局上下文中定义大量的变量污染全局命名空间 3.修改Object类的原型 4.以内联形式使用js,嵌入在HTML文件中的js代码是无法包含在外部单元

学习JavaScript设计模式(链式调用)

1.什么是链式调用 这个很容易理解,例如: $(this).setStyle('color', 'red').show(); 一般的函数调用和链式调用的区别:调用完方法后,return this返回当前调用方法的对象. function Dog(){ this.run= function(){ alert("The dog is running...."); return this;//返回当前对象 Dog }; this.eat= function(){ alert("Af

JavaScript设计模式之原型模式(Object.create与prototype)介绍

原型模式说明 说明:使用原型实例来 拷贝 创建新的可定制的对象:新建的对象,不需要知道原对象创建的具体过程: 过程:Prototype => new ProtoExam => clone to new Object; 使用相关代码: 复制代码 代码如下: function Prototype() {     this.name = '';     this.age = '';     this.sex = ''; } Prototype.prototype.userInfo = functio

JavaScript 设计模式学习 Singleton

复制代码 代码如下: /* Basic Singleton. */ var Singleton = { attribute1: true, attribute2: 10, method1: function() { }, method2: function(arg) { } }; 单件模式最主要的用途之一就是命名空间: /* GiantCorp namespace. */ var GiantCorp = {}; GiantCorp.Common = { // A singleton with c

常用的javascript设计模式

阅读目录 什么是设计模式 单体模式: 工厂模式: 单例模式 观察者模式(发布订阅模式) 策略模式 模板模式 代理模式 外观模式 设计模式太多了,貌似有23种,其实我们在平时的工作中没有必要特意去用什么样的设计模式,或者你在不经意间就已经用了设计模式当中的一种.本文旨在总结平时相对来说用的比较多的设计模式. 什么是设计模式 百度百科: 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结. 使用设计模式是为了可重用代码.让代码更容易被他人理解.

常用的Javascript设计模式小结

<Practical Common Lisp>的作者 Peter Seibel 曾说,如果你需要一种模式,那一定是哪里出了问题.他所说的问题是指因为语言的天生缺陷,不得不去寻求和总结一种通用的解决方案. 不管是弱类型或强类型,静态或动态语言,命令式或说明式语言.每种语言都有天生的优缺点.一个牙买加运动员, 在短跑甚至拳击方面有一些优势,在练瑜伽上就欠缺一些. 术士和暗影牧师很容易成为一个出色的辅助,而一个背着梅肯满地图飞的敌法就会略显尴尬. 换到程序中, 静态语言里可能需要花很多功夫来实现装饰

JavaScript设计模式之单例模式详解

最近项目不太忙,难得有时间看看书,平时挺喜欢js这门语言.也看过很多高级教程,觉得自己还是比较热衷于js的设计模式.这一次重温一下<JavaScript设计模式与开发实践>,开篇为单例模式. /** * pre 单例模式 * 定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点 * 应用:单例模式是一种常用的模式,有一些对象我们往往只需要一个, * 比如线程池.全局缓存.浏览器中的 window 对象等. */ //--------------singleton-01----------

javascript设计模式之对象工厂函数与构造函数详解

下面通过文字详解加代码分析的方式给大家分享下javascript设计模式之对象工厂函数与构造函数的相关知识. 概述使用对象字面量,或者向空对象中动态地添加新成员,是最简单易用的对象创建方法.然而,除了这两种常用的对象创建方式,JavaScript还提供了其他方法创建对象.1).使用工厂函数创建对象我们可以编写一个函数,此函数的功能就是创建对象,可将其. 概述 使用对象字面量,或者向空对象中动态地添加新成员,是最简单易用的对象创建方法. 然而,除了这两种常用的对象创建方式,JavaScript还提

JavaScript设计模式之调停者模式实例详解

本文实例讲述了JavaScript设计模式之调停者模式.分享给大家供大家参考,具体如下: 1.定义 调停者模式包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用.从而使他们可以松散偶合.当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用.保证这些作用可以彼此独立的变化.调停者模式将多对多的相互作用转化为一对多的相互作用.调停者模式将对象的行为和协作抽象化,把对象在小尺度的行为上与其他对象的相互作用分开处理. 2.使用的原因 当对象之间的交互操作很多,且每个对象的行为操

详解javascript设计模式三:代理模式

代理模式是一种对程序对象进行控制性访问的一类解决方案. 引入代理模式,其实是为了实现单一职责的面向对象设计原则. 单一职责其实就是指在一个类中(js中通常指对象和函数等),应仅有一个引起它变化的原因.这样会帮助程序设计具有良好的健壮和高内聚特性,从而当变化发生时,程序设计会尽量少的受到意外破坏. 代理模式有多种方法,保护代理.远程代理.虚拟代理.缓存代理等. 但在javascript中,代理模式最常用到的两种方法是虚拟代理和缓存代理. 虚拟代理 在理解虚拟代理时,可以将其想象为一个经纪人,客户程

JavaScript设计模式之单例模式原理与用法实例分析

本文实例讲述了JavaScript设计模式之单例模式原理与用法.分享给大家供大家参考,具体如下: 单例模式的定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点. 单例模式是一种常用的模式,有些对象只需要一个,如线程池.全局缓存.浏览器中的window对象等,这时候可以用到单例模式. 单例模式典型的应用场景:单击按钮时,页面中会出现一个登陆浮窗,而该登录浮窗是唯一的,无论单击多少次按钮,这个浮窗都会被创建一次,则适合用单例模式创建. 全局变量不是单例模式,但在JavaScript开发中,经

javascript设计模式 – 简单工厂模式原理与应用实例分析

本文实例讲述了javascript设计模式 – 简单工厂模式.分享给大家供大家参考,具体如下: 介绍:简单工厂模式是最常用的一类创建型设计模式.其中简单工厂模式并不属于GoF23个经典设计模式,它通常被作为学习其他工厂模式的基础. 定义:定义一个工厂类,它可以根据参数的不同返回不同的实例,被创建的实例通常都具有相同的父类,因为在简单工厂模式中创建实例的方法是静态方法,因此简单工厂模式又被称为静态工厂方法模式,它属于类创建型模式. 场景:我们需要写一个dialog工具类,在项目初期我们只需要考虑一

javascript设计模式 – 外观模式原理与用法实例分析

本文实例讲述了javascript设计模式 – 外观模式原理与用法.分享给大家供大家参考,具体如下: 介绍:外观模式是一种使用频率非常高的结构型设计模式,它通过引入一个外观角色来简化客户端与子系统之间的交互,为复杂的子系统调用提供一个统一的入口,隐藏系统复杂度,降低子系统与客户端的耦合度. 定义: 为子系统中的一组接口提供一个统一的入口.外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 场景:我们还是用画圆的方式来介绍下外观模式. 示例: var Rectangle = func

15个常用的javaScript正则表达式(收藏)

1 用户名正则 //用户名正则,4到16位(字母,数字,下划线,减号) var uPattern = /^[a-zA-Z0-9_-]{4,16}$/; //输出 true console.log(uPattern.test("iFat3")); 2 密码强度正则 //密码强度正则,最少6位,包括至少1个大写字母,1个小写字母,1个数字,1个特殊字符 var pPattern = /^.*(?=.{6,})(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%