不论是在程序世界里还是现实生活中,发布—订阅模式的应用都非常广泛。我们先看一下现实中的例子。 
小明最近看上了一套房子,到了售楼处之后才被告知,该楼盘的房子早已售罄。好在售楼MM告诉小明,不久后还有一些尾盘推出。开发商正在办理相关手续,手续办好后便可以购买。但到底是什么时候,目前还没有人能够知道。 
于是小明记下了售楼处的电话,以后每天都会打电话过去询问是不是已经到了购买时间。除了小明,还有小红,小强,小龙也会每天向售楼处咨询这个问题。一个星期过后,售楼MM决定辞职,因为厌倦了每天回答1000个相同的电话。 
当然现实中没有这么笨的销售公司,实际上故事是这样的:小明离开之前,把电话号码留在售楼处。售楼MM答应他,新楼盘一推出就马上发信息通知小明。小红、小强、小龙也是一样,他们的电话号码都被记在售楼处的花名册上,新楼盘推出的时候,售楼MM会翻开花名册,遍历上面的电话号码,依次发送一条短信通知他们。

发布订阅模式的优点

    1. 可以广泛应用于异步编程,它可以代替我们传统的回调函数,我们不需要关注对象在异步执行阶段的内部状态,我们只关心事件完成的时间点。

    2. 取代对象之间硬编码通知机制,一个对象不必显式调用另一个对象的接口,而是松耦合的联系在一起 
      虽然不知道彼此的细节,但不影响相互通信。更重要的是,其中一个对象改变不会影响另一个对象。

我们实现一个简单地发布订阅模型:

 // 首先定义消息的发布者
const salesoffice = {}; // 定义缓存列表,存放订阅者的回调函数列表;
salesoffice.clientList =[]; // 设置订阅者 salesoffice.listen = function(key, fn){
if(!this.clientList[key]) {
this.clientList[key] = [];
}
this.clientList[key].push(fn);
} // 设置发布事件
salesoffice.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);
}
} //示例 salesoffice.listen('aaaaa' , function(a, b){
console.log(a);
console.log( b);
}) salesoffice.listen('abcde' , function(a, b){
console.log(a);
console.log(b);
console.log(a+b);
}) console.log(salesoffice); salesoffice.trigger('aaaaa' , 100 , 200); // 100 200 300 salesoffice.trigger('abcde', 111 , 222); // 111 222 333

一个通用的发布订阅模型和事件

 // 定义发布/订阅模型
const event = {
// 设置缓存列表,存放订阅者的回调函数列表
list : [],
// 设置订阅者
listen : function(key , fn){
if(!this.list[key]){
this.list[key] = [];
}
// 将订阅的消息添加到缓存列表中
this.list[key].push(fn);
}, // 发布事件
trigger : function() {
const key = Array.prototype.shift.call(arguments),
fns = this.list[key];
if(!fns || fns.length === 0){
return false;
}
for(let i = 0 , fn ; fn = fns[i++];){
fn.apply(this, arguments);
}
}, // 取消订阅
remove : function(key , fn){
const fns = this.list[key];
// 如果key对应的消息没有订阅过的话,则返回
if(!fns) {
return false;
}
// 如果没有传入具体的回调函数,表示需要取消key对应消息的所有订阅
if(!fn) {
delete this.list[key]; //如果没有后续参数,则删除整个回调数组
}else {
for(let i = fns.length - 1 ; i>=0 ;i--) {
const _fn = fns[i];
if(_fn === fn) {
fns.splice( i, 1); // 删除订阅者的回调函数
}
}
}
}
}; const initEvent = function(obj) {
for(let i in event) {
obj[i] = event[i];
}
}; const shoeobj = {}; initEvent(shoeobj); shoeobj.listen('abcd' , function(a, b) {
console.log(a);
console.log(b);
}) shoeobj.listen('efgh' , function(a, b){
console.log(a);
console.log(b);
}) shoeobj.trigger('abcd' , 100 ,200); // 100 200 shoeobj.trigger('efgh' , 300, 500); // 300 500 shoeobj.remove('abcd'); shoeobj.trigger('abcd', 20, 50); // false

Javascript实现简单地发布订阅模式的更多相关文章

  1. js 最简单的发布订阅模式

    let _subscriber: any; function autorun(subscriber: Function) { _subscriber = subscriber; _subscriber ...

  2. Javascript中理解发布--订阅模式

    Javascript中理解发布--订阅模式 阅读目录 发布订阅模式介绍 如何实现发布--订阅模式? 发布---订阅模式的代码封装 如何取消订阅事件? 全局--发布订阅对象代码封装 理解模块间通信 回到 ...

  3. javascript设计模式——发布订阅模式

    前面的话 发布—订阅模式又叫观察者模式,它定义对象间的一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知.在javascript开发中,一般用事件模型来替代传统的发布—订阅模 ...

  4. [转] Javascript中理解发布--订阅模式

    发布订阅模式介绍 发布---订阅模式又叫观察者模式,它定义了对象间的一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象都将得到通知. 现实生活中的发布- ...

  5. [转] JavaScript设计模式之发布-订阅模式(观察者模式)-Part1

    <JavaScript设计模式与开发实践>读书笔记. 发布-订阅模式又叫观察者模式,它定义了对象之间的一种一对多的依赖关系.当一个对象的状态发生改变时,所有依赖它的对象都将得到通知. 例如 ...

  6. 【转】Javascript中理解发布--订阅模式

    Javascript中理解发布--订阅模式 阅读目录 发布订阅模式介绍 发布---订阅模式又叫观察者模式,它定义了对象间的一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时 ...

  7. 《JavaScript设计模式与开发实践》-- 发布-订阅模式

    详情个人博客:https://shengchangwei.github.io/js-shejimoshi-fabudingyue/ 发布-订阅模式 1.定义 发布-订阅模式:发布-订阅模式又叫观察者模 ...

  8. JavaScript设计模式(发布订阅模式)

    发布—订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知.在JavaScript开发中,我们一般用事件模型来替代传统的发布—订阅模式 ...

  9. 第五章 --- 关于Javascript 设计模式 之 发布-订阅模式

    先来个最简单的 发布订阅模式 document.body.addEventListener('click',function(){ alert(123); }); document.body.clic ...

随机推荐

  1. python接口自动化(三十一)--html测试报告通过邮件发出去——下(详解)

    简介 本篇总结了 QQ (SSL)邮箱和 163(非SSL) 邮箱发送邮件,专治各种不行,总之看完这篇以后麻麻再也不用担心我的邮件收不到了.以下代码兼容 python2 和 python3,运行无异常 ...

  2. 基于Actor模型的CQRS、ES解决方案分享

    开场白 大家晚上好,我是郑承良,跟大家分享的话题是<基于Actor模型的CQRS/ES解决方案分享>,最近一段时间我一直是这个话题的学习者.追随者,这个话题目前生产环境落地的资料少一些,分 ...

  3. STM32F072从零配置工程-实现delay功能

    因为是使用SysTick来作为延时时钟,因此在这里给出SysTick时钟的寄存器: CTRL:SysTick控制及状态寄存器 位段 名称 类型 复位值 描述 16 COUNTFLAG R/W 0 如果 ...

  4. [记录]一则HTTP配置文件参考记录

    # cat ../conf/httpd.conf | grep -vE "^$|^#" ServerTokens OS ServerRoot "/etc/httpd&qu ...

  5. [原创]Flask+uwsgi+virtualenv+nginx部署配置

    1.创建工程python2.7版本虚目录: #virtualenv -p /usr/bin/python2.7 CDN_resource #cd CDN_resource #source ./bin/ ...

  6. Python3安装与使用urllib2包之小坑

    Python3 安装urllib2包之小坑 Python3.6.6或者说python3.x找不到urllib2语法问题修改之后,会报一个没有安装urllib2的包的错误. 通过pip install ...

  7. python 面向对象编程 - 小游戏

    面向对象写的小游戏 欢迎玩耍 class Omnicience: camp = 'Omniscience' def __init__(self, name, atk=100, hp=1000, mp= ...

  8. C#5.0新增功能01 异步编程

    连载目录    [已更新最新开发文章,点击查看详细] 如果需要 I/O 绑定(例如从网络请求数据或访问数据库),则需要利用异步编程. 还可以使用 CPU 绑定代码(例如执行成本高昂的计算),对编写异步 ...

  9. JS+Jquery自定义格式导出HTML为Word(下列插件同样可以用于Excel导出)

    这里的word导出主要采用了jquery.wordexport.js.FileSaver.js,做功能之前我也是找了很多网上的资料,里面涉及到js导出word的用的都是这个插件,只是在自定义样式这一块 ...

  10. 转载——Asp.Net MVC+EF+三层架构的完整搭建过程

    转载http://www.cnblogs.com/zzqvq/p/5816091.html Asp.Net MVC+EF+三层架构的完整搭建过程 架构图: 使用的数据库: 一张公司的员工信息表,测试数 ...