观察者模式

观察者模式也叫“订阅者/发布者”模式,定义对象间的一种一对多的依赖关系,发布者可以向所有订阅者发布消息。

观察者模式被广泛地应用于JavaScript客户端编程中。所有的浏览器事件(mouseover,keypress等)都是使用观察者模式的例子。

使用这个模式的最主要目的就是促进对象之间的解耦(弱化对象之间的联系)。在观察者模式中,一组对象订阅另一个对象的指定活动并得到通知。

如:

document.body.addEventListener('click',function(){
alert(2);
},false);

以上代码订阅了document.body的click事件,当body被点击时,body便会向订阅者发布消息;

实现观察者模式的一般步骤:

  1. 先指定谁充当发布者;
  2. 给发布者添加一个缓存列表,用于存放回调函数以便通知订阅者;
  3. 发布消息时,发布者会遍历这个缓存列表,依次触发里面存放的订阅者回调函数;还可在回调函数内加入一些参数;

    (也可先发布消息,将消息保存起来,当有订阅者时就将该消息重新发布给他)
发布-订阅模式的通用实现:
var Publisher = (function(){
//listenerList用来保存一系列的key,每个key为保存了所有订阅者函数fn的数组{ keyA:[fn1,fn2...], keyB:[...]...}
//类似:可以为同一事件注册多个回调函数
var listenerList = {};
return {
addListener: function(key,fn){
if(!listenerList[key]){
listenerList[key] = [];
}
if(listenerList[key].indexOf(fn) === -1){ //检测fn是否已订阅,注意indexOf方法不支持IE9以下,可用for循环代替
listenerList[key].push(fn);
}
},
publish: function(){
var key = Array.prototype.shift.call(arguments),
fns = listenerList[key];
if(!fns||fns.length === 0){
return false;
}
for(var i = 0,fn;fn = fns[i++];){
fn.apply(this,arguments);
}
},
removeListener: function(key,fn){
var fns = listenerList[key];
if(!fns){
return false;
}
if(!fn){ //若没指定fn,则表示取消所有订阅
fns && (fns.length = 0);
}else{ //可直接用fns.splice(listenerList[key].indexOf(fn),1);但indexOf方法不支持IE9以下
for(var l = fns.length - 1; l >= 0; l--){
if(fns[l] === fn){
fns.splice(l,1);
}
}
}
}
};
})(); Publisher.addListener('month',function(num){ //订阅month
console.log('本月数量: '+num);
});
Publisher.addListener('month',function(price){
console.log('本月价格: '+price);
});
Publisher.addListener('week',function(num){
console.log('本周数量: '+num);
});
Publisher.publish('month',123); //手动发布消息
//本月数量: 123
//本月价格: 123
Publisher.publish('week',5);
//本周数量: 5

实际应用:

$.ajax('http://xxx.com?login',function(data){
Publisher.publish('loginSuccess',data); //若登录成功则向所有订阅者发布登录成功的消息
});
//以下在各个模块添加订阅消息
var header = (function () {
Publisher.addListener('loginSuccess', function (data) {
header.setAvatar(data.avatar);
});
return {
setAvatar: function (data) {
console.log('设置header模块的头像')
}
}
})();
var nav = (function () {
Publisher.addListener('loginSuccess', function (data) {
nav.setAvatar(data.avatar);
});
return {
setAvatar: function (avatar) {
console.log('设置header模块的头像')
}
}
})();
//...可随意添加其他模块

参考文献:

《JavaScript模式》

《JavaScript设计模式与开发实践》

轻松掌握:JavaScript观察者模式的更多相关文章

  1. 轻松学习 JavaScript——第 6 部分:JavaScript 箭头函数

    JavaScript箭头函数是ECMAScript 6中引入的编写函数表达式的一种简便方法.通常,在JavaScript中,可以通过两种方式创建函数: 函数语句. 函数表达式. 可以如下所示创建函数语 ...

  2. 轻松学习JavaScript十八:DOM编程学习之DOM简单介绍

    一DOM概述 DOM(文档对象模型)是HTML和XML的应用程序接口(API).DOM将把整个页面规划成由节点层级构成的文档. DOM描绘了一个层次化的节点树,执行开发者加入,移除和改动页面的某一部分 ...

  3. 轻松理解JavaScript闭包

    摘要 闭包机制是JavaScript的重点和难点,本文希望能帮助大家轻松的学习闭包 一.什么是闭包? 闭包就是可以访问另一个函数作用域中变量的函数. 下面列举出常见的闭包实现方式,以例子讲解闭包概念 ...

  4. 轻松理解JavaScript之AJAX

    摘要 AJAX技术是网页构建的必备技能之一,本文希望能帮助大家轻松的学习这项技术 一.什么是ajax? ajax(异步javascript xml) 能够刷新局部网页数据而不是重新加载整个网页. 二. ...

  5. 分针网—每日分享: 怎么轻松学习JavaScript

    js给初学者的印象总是那么的"杂而乱",相信很多初学者都在找轻松学习js的途径.   我试着总结自己学习多年js的经验,希望能给后来的学习者探索出一条"轻松学习js之路& ...

  6. JavaScript观察者模式

    观察者模式观察者模式又叫发布订阅模式(Publish/Subscribe),它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使得 ...

  7. 怎么轻松学习JavaScript

    js给初学者的印象总是那么的“杂而乱”,相信很多初学者都在找轻松学习js的途径.我试着总结自己学习多年js的经验,希望能给后来的学习者探索出一条“轻松学习js之路”.js给人那种感觉的原因多半是因为它 ...

  8. 理解javascript观察者模式(订阅者与发布者)

    什么是观察者模式? 观察者模式又叫做发布订阅模式,它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生改变时就会通知所有观察着对象.它是由两类对象组成,主题和观察者 ...

  9. Javascript观察者模式(Object.defineProperty、Reflect和Proxy实现)

    什么是观察者模式? 答:在数据发生改变时,对应的处理函数自动执行.函数自动观察数据对象,一旦对象有变化,函数就会自动执行. 参考<原生JavaScript实现观察者模式>(https:// ...

随机推荐

  1. Sql Server系列:数据库操作

    1 创建数据库 1.1 CREATE DATABASE语法 CREATE DATABASE database_name [ ON [ PRIMARY ] <filespec> [ ,... ...

  2. 【原创】开源Math.NET基础数学类库使用(01)综合介绍

                   本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新  开源Math.NET基础数学类库使用总目录:[目录]开源Math.NET基础数学类库使用总目录 前言 ...

  3. 应用程序框架实战十四:DDD分层架构之领域实体(基础篇)

    上一篇,我介绍了自己在DDD分层架构方面的一些感想,本文开始介绍领域层的实体,代码主要参考自<领域驱动设计C#2008实现>,另外参考了网上找到的一些示例代码. 什么是实体 由标识来区分的 ...

  4. EF Code First 主键对应多个外键

    这是一位朋友提出的疑问,EF 映射主键可以对应多个外键吗?如果外键设置级联删除会发生什么情况?下面做一个测试,示例实体代码: public class Blog { public Blog() { P ...

  5. 【记录】JS 获取 URL 中文参数编码

    比如 URL:http://www.xxxx.com/中文参数 这个在 js 获取"中文参数"的时候会出现乱码. 解决方法:decodeURIComponent(获取的中文参数);

  6. geotrellis使用(二十)geotrellis1.0版本新功能及变化介绍

    目录 前言 变化情况介绍 总结 一.前言        之前版本是0.9或者0.10.1.0.10.2,最近发现更新成为1.0.0-2077839.1.0应该也能称之为正式版了吧.发现其中有很多变化, ...

  7. iOS_MJRefrash的详解以及使用

    MJRefresh Github 效果动态图来这里看吧 该博客Demo下载地址 一. MJRefresh的类解释. 1.MJRefreshComponent              所有刷新控件的基 ...

  8. PHP数组及简单函数

    PHP函数: 1.简单函数 四要素:返回类型,函数名,参数列表,函数体 function Show() { echo "hello"; } Show(); 运行结果:hellow ...

  9. POST方式提交表单时,后台接受实体如果继承了父类,将无法映射表单对应数据

    引言 刚才在做一个post提交表单时,我在表单里放了几个隐藏域用来存放数据,表单name属性和后台实体属性签名保持一致.只是后台Action参数包含继承关系,所以无法获取到表单对应的值.刚开始一直纳闷 ...

  10. maven全局配置文件settings.xml详解

    概要 settings.xml有什么用? 如果在Eclipse中使用过Maven插件,想必会有这个经验:配置settings.xml文件的路径. settings.xml文件是干什么的,为什么要配置它 ...