一、前言

  发布订阅模式,基于一个主题/事件通道,希望接收通知的对象(称为subscriber)通过自定义事件订阅主题,被激活事件的对象(称为publisher)通过发布主题事件的方式被通知。

  就和用户订阅微信公众号道理一样,一个公众号可以被多个用户同时订阅,当公众号有新增内容时候,只要发布就好了,用户就能接收到最新的内容。

  js中的事件监听机制就是一种观察者模式。

二、和观察者模式的区别

  观察者模式:一个对象(称为subject)维持一系列依赖于它的对象(称为observer),将有关状态的任何变更自动通知给它们(观察者)。

  1、Observer模式要求观察者必须订阅内容改变的事件,定义了一个一对多的依赖关系;
       2、Publish/Subscribe模式使用了一个主题/事件通道,这个通道介于订阅着与发布者之间;
       3、观察者模式里面观察者「被迫」执行内容改变事件(subject内容事件);发布/订阅模式中,订阅着可以自定义事件处理程序;
       4、观察者模式两个对象之间有很强的依赖关系;发布/订阅模式两个对象之间的耦合读底

这是一个简单的实现,主要是创建一个对象,有三个属性(容器,订阅方法,发布方法)。将订阅者放入容器,发布,触发容器内的函数。

(function(){

    //
function Public(){
//存放订阅者的容器
this.subscribers=[];
//添加订阅者
this.addSubscribers=function(fn){
let isExit = this.subscribers.some(function(sub){
return fn == sub;
})
if(!isExit){
this.subscribers.push(fn);
}
return this;
} //发布消息
this.deliver = function(data){
this.subscribers.forEach(function(fn){
fn(data);
})
return this;
}
} let a = function(data){
console.log("a:"+data);
}
let b = function(data){
console.log("b:"+data);
} let c = function(data){
console.log("c:"+data);
} var pub = new Public();
pub.addSubscribers(a).addSubscribers(b).addSubscribers(c);
pub.deliver("消息");
})()

2、可以看到观察者模式有如下优点

  a、每一个订阅者都是相互独立的只和发布者有关系,与发布者是一对多的关系,也可以是一对一的关系。
  b、每一个订阅者可以根据自己的需求来调用,而不影响其它订阅者
  c、与第一种方式相比,第二种方式的代码可读性、可维护性强;

这是一个完整的实现

(function(win){
function Public(){
this.handlers={};
}
Public.prototype = {
//订阅事件
on:function(eventType,eventHandle){
var self = this;
if(!(eventType in self.handlers)){
self.handlers[eventType] = [];
}
self.handlers[eventType].push(eventHandle);
return this;
},
emit:function(eventType){
//如果调用函数传了多个参数,eventType指第一个参数,arguments是一个对象,参数序号是key指,同时也给他length
//看起来像数组,其实不是数组。
var self = this;
//去除第一个事件类型的参数,使用call改变this指向
//使用slice的对象需要由length属性,所以arguments才能使用成功。
var handleArgs = Array.prototype.slice.call(arguments,1);
console.log(handleArgs);
for (var i =0; i<self.handlers[eventType].length;i++) {
//使用apply,订阅者的调用对象就是Public,不适用就是数组对象。
self.handlers[eventType][i].apply(self,handleArgs);
}
return this;
},
off:function(eventType,eventHandle){
var currentEvent = this.handlers[eventType];
var len = 0;
if(currentEvent){
len = currentEvent.length;
if(eventHandle == undefined){
currentEvent[eventType] = [];
}else{
for (var i = len-1;i >= 0;i--) {
if(currentEvent[i] == eventHandle){
currentEvent.splice(i,1);
}
}
} }
}
}
var a = function(data){
console.log(this);
console.log("a"+data);
}
var b =function(data){
console.log("b"+data); }
   var pub = new Public();
pub.on("click",a).on("click",b);
pub.emit("click","xiaoxi"); })(window)

参考博主的文章:https://www.cnblogs.com/leaf930814/p/9014200.html

js设计模式-发布/订阅模式的更多相关文章

  1. js设计模式--发布订阅模式

    前言 本系列文章主要根据<JavaScript设计模式与开发实践>整理而来,其中会加入了一些自己的思考.希望对大家有所帮助. 概念 发布-订阅模式又叫观察者模式,它定义对象间的一种一对多的 ...

  2. [转]js设计模式—发布订阅模式

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

  3. JS的发布订阅模式

    JS的发布订阅模式 这里要说明一下什么是发布-订阅模式 发布-订阅模式里面包含了三个模块,发布者,订阅者和处理中心.这里处理中心相当于报刊办事大厅.发布者相当与某个杂志负责人,他来中心这注册一个的杂志 ...

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

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

  5. 设计模式-发布订阅模式(javaScript)

    1. 前言 2. 什么是发布订阅模式 3. 发布订阅优缺点 4. 举例 4. 总结 1. 前言 发布订阅者模式是为了发布者和订阅者之间避免产生依赖关系,发布订阅者之间的订阅关系由一个中介列表来维护.发 ...

  6. javascript 设计模式 -- 发布/订阅模式

    直接上代码: index.html : <!DOCTYPE html> <html lang="en"> <head> <meta cha ...

  7. js 实现发布订阅模式

    /* Pubsub */ function Pubsub(){ //存放事件和对应的处理方法 this.handles = {}; } Pubsub.prototype = { //传入事件类型typ ...

  8. js 设计模式:观察者和发布订阅模式

    总是把这两个当作同一个模式,但其实是不太一样的,现在重温一下. 观察者模式 观察者直接订阅目标,当目标触发事件时,通知观察者进行更新 简单实现 class Observer { constructor ...

  9. JS设计模式(5)发布订阅模式

    什么是发布订阅模式(观察者模式)? 定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新. 主要解决:一个对象状态改变给其他对象通知的问题,而且 ...

随机推荐

  1. Mac Mysql [ERR] 2006 - MySQL server has gone away

    Mac mysql 安装后,导入sql数据,出现这个错误: 处理方式,是因为sql文件太大,需要修改mysql的配置.如果没有my.cnf就自己建一个. cd /etc sudo vim my.cnf ...

  2. bzoj-1192 [HNOI2006]鬼谷子的钱袋(水题)

    题目链接: [HNOI2006]鬼谷子的钱袋 Time Limit: 10 Sec  Memory Limit: 162 MB Description 鬼谷子非常聪明,正因为这样,他非常繁忙,经常有各 ...

  3. SQLite数据库框架--FMDB简单介绍

    1.什么是FMDB FMDB是iOS平台的SQLite数据库框架 FMDB以OC的方式封装了SQLite的C语言API 2.FMDB的优点 使用起来更加面向对象,省去了很多麻烦.冗余的C语言代码 对比 ...

  4. Eclipse 插件管理

    查看已安装的插件: [help]⇒ [About Eclipse]⇒ [Installed Softwares] 1. 常用插件 maven:安装步骤如下: [help]⇒ [Install new ...

  5. javascript 反斜杠\

    通常,我们在动态给定一个div的innerHTML时,通常是样做的: <div id="demo1" /> <SCRIPT> var demo= docum ...

  6. NDK相关收藏【转】

    http://blog.csdn.net/column/details/anidea-ndk.html   [转] 作者:conowen@大钟

  7. python pip安装第三方模块

    一.pip工具使用 安装windows版本python,自带pip工具.2者路径相同. 如果设置了环境路径,可以直接在命令提示符窗口下尝试运行pip.如果没有设置环境路径,可以先cd命令到pip工具的 ...

  8. 洛谷 P2761 软件补丁问题 【spfa】

    -为什么最短路的题会出现在网络流24里?? 因为范围是15所以直接把每个状态作为一个点,向它能转移到的点连有向边即可.可以不用建图(据说建图存不下?),直接枚举m个转移方案.位运算比较麻烦注意不要写错 ...

  9. unsign 字段相减出现负数解决方法

    在项目中做数据统计的时候需要用到几个字段相减得到想要的值,但是因为字段都是无符号,相减出现mysql 错误 BINGINT UNSIGNED VALUE ..  在c语言中两个无符号相减值为负数,该值 ...

  10. 【SQL】从待选项中随机选一个

    由于SQL Server没有数组类型,所以在面对“从若干待选项中选一个”这种需求时,往往要采取变通办法,比如弄个‘a|b|c’这样的字符串然后对字符串进行处理:又或者把待选项塞进一个临时表,然后把问题 ...