不论是在程序世界里还是现实生活中,发布—订阅模式的应用都非常广泛。我们先看一下现实中的例子。 
小明最近看上了一套房子,到了售楼处之后才被告知,该楼盘的房子早已售罄。好在售楼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. CAxWindow

    AtlAxWinInit(); CAxWindow m_wndFlashPlayer; CComPtr<IShockwaveFlash> m_FlashPtr; CComPtr<IU ...

  2. 洛谷P2790 ccj与zrz之积木问题 题解

    题目链接:https://www.luogu.org/problemnew/show/P2790 这题码量稍有点大... 分析: 这道题模拟即可.因为考虑到所有的操作vector可最快捷的实现,所以数 ...

  3. Excel催化剂开源第3波-修复ExcelCom加载项失效问题及WPS可调用Com加载项的方法

    为了还原一个干净无侵扰的网络世界,本文将不进行大规模地分发,若您觉得此文有用,不妨小范围地分享到真正有需要的人手中 功能概述 修复ExcelCom加载项常见问题,如每次需重新勾选COM加载项或COM加 ...

  4. SGU495 Kids andPrices[期望DP]

    也许更好的阅读体验 \(\mathcal{Description}\) 有\(n\)个格子,每次等概率随机给一个格子染色,问涂\(m\)次后期望有多少格子被染色了 \(\mathcal{Solutio ...

  5. Html5web全栈前端开发_angular框架

    昵称领取全套angular视频教程 一.Typescript typescript简称ts,是js语法的超集,很多js新的语法就借鉴了ts语法.ts是由微软团队维护的 1.1 TS简介 1.1.1 G ...

  6. jmeter环境变量

    jmeter环境变量配置jmeter环境变量时,同时也需要配置Java变量(jdk最好使用1.7及1.7以上的版本)1.配置jdk环境变量安装jdk正常安装,一路默认就好,记住安装路径,配置环境变量时 ...

  7. django第三次(转自刘江)

    所有的模型字段都可以接收一定数量的参数,比如CharField至少需要一个max_length参数.下面的这些参数是所有字段都可以使用的,并且是可选的. null 该值为True时,Django在数据 ...

  8. 2.2.2python的BeautifulSoup库

    from bs4 import BeautifulSoupimport rebroken_html = '<ul class="country"><li>A ...

  9. [解决方案]IIS配置后报错404,500,502等系列问题

    很多时候刚部署完服务器的IIS以后,第一次部署站点都会出现形形色色,各种各样的报错问题,但这些问题大同小异,我这里就给大家提供的解决的方案,以达到以不变应万变的效果 目的:让大家学会处理类似问题的方法 ...

  10. 日常用shell命令

    递归更改文件夹权限:chmod -R 767 文件名 mac启动apache sudo apachectl start/restart mac停止apache sudo apachectl stop ...