JavaScript设计模式(发布订阅模式)
一、简单的发布-订阅模式
var salesOffices = {}; // 定义售楼处
salesOffices.clientList = []; // 缓存列表,存放订阅者的回调函数
salesOffices.listen = function( fn ){ // 增加订阅者
this.clientList.push( fn ); // 订阅的消息添加进缓存列表
};
salesOffices.trigger = function(){ // 发布消息
for( var i = 0, fn; fn = this.clientList[ i++ ];) {
fn.apply( this, arguments ); // arguments 是发布消息时带上的参数
}
};
salesOffices.listen( function( price, squareMeter ) { // 小明订阅者
console.log( '价格= ' + price );
console.log( 'squareMeter= ' + squareMeter );
});
salesOffices.listen( function( price, squareMeter ) { // 小红订阅者
console.log( '价格= ' + price );
console.log( 'squareMeter= ' + squareMeter );
});
salesOffices.trigger( 2000000, 88 ); // 输出: 价格= 2000000,squareMeter= 88 价格= 2000000,squareMeter= 88
salesOffices.trigger( 3000000, 110 ); // 输出: 价格= 3000000,squareMeter= 110 价格= 3000000,squareMeter= 110
var salesOffices = {}; // 定义售楼处
salesOffices.clientList = {}; // 缓存列表,存放订阅者的回调函数
salesOffices.listen = function( key, fn ){ // 增加订阅者
if(!this.clientList[key]) {
this.clientList[key] = []
}
this.clientList[key].push( fn ); // 订阅的消息添加进缓存列表
};
salesOffices.trigger = function(){ // 发布消息
var key = Array.prototype.shift.call( arguments ), // 取出消息类型
fns = this.clientList[ key ]; // 取出该消息对应的回调函数集合
if ( !fns || fns.length === 0 ){ // 如果没有订阅该消息,则返回
return false;
}
for( var i = 0, fn; fn = fns[ i++ ];) {
fn.apply( this, arguments ); // arguments 是发布消息时带上的参数
}
};
salesOffices.listen( 'squareMeter88', function( price ) { // 小明订阅者
console.log( '价格= ' + price );
});
salesOffices.listen( 'squareMeter110', function( price ) { // 小红订阅者
console.log( '价格= ' + price );
});
salesOffices.trigger( 'squareMeter88', 2000000); // 输出: 价格= 2000000
salesOffices.trigger( 'squareMeter110', 3000000); // 输出: 价格= 3000000
二、发布-订阅模式的通用实现
var event = {
clientList: [],
listen: function( key, fn ){
if ( !this.clientList[ key ] ){
this.clientList[ key ] = [];
}
this.clientList[key].push( fn ); // 订阅的消息添加进缓存列表
},
trigger: function() {
var key = Array.prototype.shift.call( arguments ), // (1);
fns = this.clientList[ key ];
if ( !fns || fns.length === 0 ){ // 如果没有绑定对应的消息
return false;
}
for( var i = 0, fn; fn = fns[ i++ ]; ){
fn.apply( this, arguments ); // (2) // arguments 是 trigger 时带上的参数
}
}
}
var installEvent = function( obj ){
for ( var i in event ){
obj[ i ] = event[ i ];
}
};
var salesOffices = {};
installEvent( salesOffices );
salesOffices.listen( 'squareMeter88', function( price ){
console.log( '价格= ' + price ); // 小明订阅消息
});
salesOffices.listen( 'squareMeter100', function( price ){
console.log( '价格= ' + price ); // 小红订阅消息
});
salesOffices.trigger( 'squareMeter88', 2000000 ); // 输出:2000000
salesOffices.trigger( 'squareMeter100', 3000000 ); // 输出:3000000
event.remove = function( key, fn ){
var fns = this.clientList[ key ];
if ( !fns ){ // 如果 key 对应的消息没有被人订阅,则直接返回
return false;
}
if ( !fn ){ // 如果没有传入具体的回调函数,表示需要取消 key 对应消息的所有订阅
fns && ( fns.length = 0 );
}else{
for ( var l = fns.length - 1; l >=0; l-- ){ // 反向遍历订阅的回调函数列表
var _fn = fns[ l ];
if ( _fn === fn ){
fns.splice( l, 1 ); // 删除订阅者的回调函数
}
}
}
};
var salesOffices = {};
var installEvent = function( obj ){
for ( var i in event ){
obj[ i ] = event[ i ];
}
}
installEvent( salesOffices );
salesOffices.listen( 'squareMeter88', fn1 = function( price ){ // 小明订阅消息
console.log( '价格= ' + price );
});
salesOffices.listen( 'squareMeter88', fn2 = function( price ){ // 小红订阅消息
console.log( '价格= ' + price );
});
salesOffices.remove( 'squareMeter88', fn1 ); // 删除小明的订阅
salesOffices.trigger( 'squareMeter88', 2000000 ); // 输出:2000000
三、全局的发布-订阅对象
var Event = (function(){
var clientList = {},
listen,
trigger,
remove;
listen = function( key, fn ){
if ( !clientList[ key ] ){
clientList[ key ] = [];
}
clientList[ key ].push( fn );
};
trigger = function(){
var key = Array.prototype.shift.call( arguments ),
fns = clientList[ key ];
if ( !fns || fns.length === 0 ){
return false;
}
for( var i = 0, fn; fn = fns[ i++ ]; ){
fn.apply( this, arguments );
}
};
remove = function( key, fn ){
var fns = clientList[ key ];
if ( !fns ){
return false;
}
if ( !fn ){
fns && ( fns.length = 0 );
} else {
for ( var l = fns.length - 1; l >=0; l-- ){
var _fn = fns[ l ];
if(_fn === fn){
fns.splice( l, 1 );
}
}
}
};
return {
listen: listen,
trigger: trigger,
remove: remove
}
})();
Event.listen( 'squareMeter88', function( price ){ // 小红订阅消息
console.log( '价格= ' + price ); // 输出:'价格=2000000'
});
Event.trigger( 'squareMeter88', 2000000 ); // 售楼处发布消息
四、总结
JavaScript设计模式(发布订阅模式)的更多相关文章
- javascript设计模式——发布订阅模式
前面的话 发布—订阅模式又叫观察者模式,它定义对象间的一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知.在javascript开发中,一般用事件模型来替代传统的发布—订阅模 ...
- javascript 设计模式 -- 发布/订阅模式
直接上代码: index.html : <!DOCTYPE html> <html lang="en"> <head> <meta cha ...
- 设计模式-发布订阅模式(javaScript)
1. 前言 2. 什么是发布订阅模式 3. 发布订阅优缺点 4. 举例 4. 总结 1. 前言 发布订阅者模式是为了发布者和订阅者之间避免产生依赖关系,发布订阅者之间的订阅关系由一个中介列表来维护.发 ...
- js设计模式--发布订阅模式
前言 本系列文章主要根据<JavaScript设计模式与开发实践>整理而来,其中会加入了一些自己的思考.希望对大家有所帮助. 概念 发布-订阅模式又叫观察者模式,它定义对象间的一种一对多的 ...
- [转]js设计模式—发布订阅模式
发布—订阅模式又叫观察者模式,它定义对象间的一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知.在javascript开发中,一般用事件模型来替代传统的发布—订阅模式.本文将 ...
- [转] 浅析JavaScript设计模式——发布-订阅/观察者模式
前一段时间一直在写CSS3的文章 一直都没写设计模式 今天来写写大名鼎鼎观察者模式 先画张图 观察者模式的理解 我觉得还是发布-订阅模式的叫法更容易我们理解 (不过也有的书上认为它们是两种模式……) ...
- js设计模式-发布/订阅模式
一.前言 发布订阅模式,基于一个主题/事件通道,希望接收通知的对象(称为subscriber)通过自定义事件订阅主题,被激活事件的对象(称为publisher)通过发布主题事件的方式被通知. 就和用户 ...
- Javascript设计模式之发布-订阅模式
简介 发布-订阅模式又叫做观察者模式,他定义了一种一对多的依赖关系,即当一个对象的状态发生改变的时候,所有依赖他的对象都会得到通知. 回忆曾经 作为一名前端开发人员,给DOM节点绑定事件可是再频繁不过 ...
- 理解JavaScript设计模式与开发应用中发布-订阅模式的最终版代码
最近拜读了曾探所著的<JavaScript设计模式与开发应用>一书,在读到发布-订阅模式一章时,作者不仅给出了基本模式的通用版本的发布-订阅模式的代码,最后还做出了扩展,给该模式增加了离线 ...
- [转] JavaScript设计模式之发布-订阅模式(观察者模式)-Part1
<JavaScript设计模式与开发实践>读书笔记. 发布-订阅模式又叫观察者模式,它定义了对象之间的一种一对多的依赖关系.当一个对象的状态发生改变时,所有依赖它的对象都将得到通知. 例如 ...
随机推荐
- python之json读写
#将字典转json并写入文件 import json i=3 j=5 a={'a':i,'b':j} js=json.dumps(a) print(js) with open("/Users ...
- moveUp()
这个函数内容有点多,想讲一下大概思路: 向上移有两种情况1.前面为空白 这种情况有两个步骤 (1)将人当前的位置设置为空白(0), (2)再讲人前面的位置设置为人(2)2.前面为箱子 当前面为箱子时有 ...
- Leetcode题目64.最小路径和(动态规划-中等)
题目描述: 给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小. 说明:每次只能向下或者向右移动一步. 示例: 输入: [ [1,3,1], [1, ...
- Linux如何修改环境变量
如果想要环境变量永久生效可以修改下面两个文件中的任何一个: 1 /etc/profile 2 .bash_profile 其中,/etc/profile是全局的环境变量,对所有用户生效,而.bash_ ...
- Flutter制作Toast会自己关闭的消息提示框
项目中需要用到类似安卓的Toast提示框,因为flutter中又没有相关组件,然后在网上看到个不错的,地址https://www.jianshu.com/p/cf7877c9bdeb,然后拿过来修改了 ...
- 在windows系统搭建并运行一个Flutter项目
搭建Flutter之前需要已经安装好相应的Flutter开发环境,如果没安装好相应环境的可以查看在windows系统搭建Flutter开发环境 搭建Flutter项目可以通过命令行搭建,或者通过and ...
- qt 之http学习
在Qt网络编程中,需要用到协议,即HTTP.它是超文本传输协议,它是一种文件传输协议. 新建工程名为“http”,然后选中QtNetwork模块,最后Base class选择QWidget.注意:如果 ...
- 计算机组成原理 — GPU 图形处理器
目录 文章目录 目录 显卡 GPU GPU 与深度学习 GPU 与 CPU 体系结构的区别 GPU 显存与 CPU 主存的区别 GPU 与 CPU 之间的数据交互方式 GPU 的体系结构 GPU 的工 ...
- Scala面向对象03
- git学习教程二之远程仓库学习
首先你需要注册一个github用户名,我的github账户是:1654218052@qq.com 由于本地的git仓库和github的仓库是通过SSH加密的,所以我们还需要设置一点东西哦 第1步:创建 ...