不论是在程序世界里还是现实生活中,发布—订阅模式的应用都非常广泛。我们先看一下现实中的例子。 
小明最近看上了一套房子,到了售楼处之后才被告知,该楼盘的房子早已售罄。好在售楼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. 【朝花夕拾】Android自定义View篇之(十)TouchSlop及VelocityTracker

    前言 在Android事件中,有几个比较基本的概念和知识点需要掌握.比如,表示最小移动阈值的TouchSlop,追踪事件速度的VelocityTracker,用于检测手势的GestureDetecto ...

  2. springboot项目快速搭建

    1. 问题描述 springboot的面世,成为Java开发者的一大福音,大大提升了开发的效率,其实springboot只是在maven的基础上,对已有的maven gav进行了封装而已,今天用最简单 ...

  3. vs查看派生类

    把类名拷贝到类视图中,点“派生类型”可看到此类的所有派生类.

  4. 跟着大彬读源码 - Redis 5 - 对象和数据类型(上)

    相信很多人应该都知道 Redis 有五种数据类型:字符串.列表.哈希.集合和有序集合.但这五种数据类型是什么含义?Redis 的数据又是怎样存储的?今天我们一起来认识下 Redis 这五种数据结构的含 ...

  5. HBase部署与使用

    HBase部署与使用 概述 HBase的角色 HMaster 功能: 监控RegionServer 处理RegionServer故障转移 处理元数据的变更 处理region的分配或移除 在空闲时间进行 ...

  6. android实现倒计时,最简单实现RecyclerView倒计时+SwipeRefreshLayout下拉刷新

    先上效果图: RecyclerView + SwipeRefreshLayout 实现倒计时效果 MainActivity.java package top.wintp.counttimedemo1; ...

  7. TensorFlow笔记-模型的保存,恢复,实现线性回归

    模型的保存 tf.train.Saver(var_list=None,max_to_keep=5) •var_list:指定将要保存和还原的变量.它可以作为一个 dict或一个列表传递. •max_t ...

  8. 完整使用JDBC访问数据库

    Connection con = null; PreparedStatement statement = null; ResultSet res = null; List<Student> ...

  9. myeclipse中更改默认jdk版本出错( Target is not a JDK root. System library was not found)

    原因是我的本地jdk版本是9.0,将jdk版本更改至8.0即可导入成功. jdk9.0导入myeclipse中去会有此类问题的发生,因此没有必要使用最新的jdk版本.

  10. 恢复在iterm2中当滚动光标时候触发滚动历史记录的问题

    在Iterm2中,如果你上下滚动光标(上下滑动触摸板.或者滚动鼠标滚轮),通常情况下是触发了屏幕内容上下滚动. 但是在某些异常情况下,却触发了命令行历史记录的上下滚动,效果和你连续按了多次键盘的上下键 ...