观察者模式:定义一对多的关系,让多个观察对象同时监听某一个主题对象,主题对象状态发生变化就通知所有观察者对象。所以它是由两类对像组成:Subject主题+Observer观察者。主题发布事件,观察者通过订阅事件观察主题。

Observer模式提供给关联对象一种同步通信的手段,使得主题和观察者之间保持同步通信

function observar(oldVal,newVal){
console.log(`name属性值从${oldVal}改变为${newVal}`);
}
class TargetObj{
constructor(age,name){
this.name = name;
this.age = age;
}
set name(val){
observar(name,val);
name
= val;
}

}
let targetObj = new TargetObj(22,'miya');
targetObj.name = 'Lily';
console.log(targetObj)
//name属性值从改变为miya
//name属性值从miya改变为Lily 

阮一峰大神在介绍Reflect时候,使用Proxy写了一个观察者模式的代码:

//观察者队列
const queuedObservers = new Set();
const observe = fn => queuedObservers.add(fn);
function print(){
console.log(`${person.name},${person.age}`);
}
//将观察者放入队列中
observe(print);
const person = new Proxy({name:'张三',age:22},{
set(target,key,value,receiver){
const result = Reflect.set(target,key,value,receiver);
queuedObservers.forEach(observer => observer());
return result;
}
})
person.name = '李四';
//李四,22

上面代码可以看出,观察者模式是:Observer在Subject主题对象特定活动状态改变时候获取通知。主题Subject需要一个数组类型来存储所有的订阅者。Subject和Observer之间存在依赖关系,存在耦合。

JavaScript中的事件监听机制可以理解为观察者模式,通过onclick事件绑定,然后事件主动触发。

发布—订阅模式:完全解耦,发布者和订阅者彼此不知道对方的存在,二者共享一个自定义事件的名称。它的优点非常明显,一为时间上的解耦,二为对象之间的解耦。

观察者模式中,目标对象也就是Subject管理观察者,发布-订阅模式中多了一个中间层通道。

//发布-订阅
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 i = 0,_fn;_fn = fns[i++];){
if(fn === _fn){
fns.splice(i,1);
}
}
}
}
return {
listen:listen,
trigger:trigger,
remove:remove
}
})()
Event.listen('LondonAirPlay',function(price){
console.log(`the price is ${price}`)
})
Event.trigger('LondonAirPlay',3000)
//the price is 3000 

订阅者想要订阅伦敦的机票,通过Event对象来实现了,Event对象具有listen订阅,trigger发布,remove取消等功能,订阅者和发布者之间完全是不认识的,Event类似于一个“中介者”,将订阅者和发布者联系起来。

总结:

1,Observer模式,观察者是知道Subject主题的,目标主题一直保持对观察者的记录,而publish-subscribe模式中,订阅者和发布者互相不知道对方,通过消息代理进行通信。

2,Observer模式中,观察者和主题之间存在依赖耦合关系,而发布订阅者模式则完全松耦合的。

3,多数情况下,Observer模式是同步,例如事件触发,而发布-订阅者使用的消息队列模式,大多数处理异步事件。

【完】

如来者,无所从来,亦无所去,故名如来。
                                                                 ——鸠摩罗什 《金刚经》

观察者模式(Observer)和发布-订阅者模式(Publish/Subscribe)区别的更多相关文章

  1. [JS设计模式]:观察者模式(即发布-订阅者模式)(4)

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

  2. “一切都是消息”--MSF(消息服务框架)之【发布-订阅】模式

    在上一篇,“一切都是消息”--MSF(消息服务框架)之[请求-响应]模式 ,我们演示了MSF实现简单的请求-响应模式的示例,今天来看看如何实现[发布-订阅]模式.简单来说,该模式的工作过程是: 客户端 ...

  3. “一切都是消息”--iMSF(即时消息服务框架)之【发布-订阅】模式

    MSF的名字是 Message Service Framework 的简称,由于目前框架主要功能在于处理即时(immediately)消息,所以iMSF就是 immediately Message S ...

  4. ActiveMQ发布-订阅消息模式

    一.订阅杂志我们很多人都订过杂志,其过程很简单.只要告诉邮局我们所要订的杂志名.投递的地址,付了钱就OK.出版社定期会将出版的杂志交给邮局,邮局会根据订阅的列表,将杂志送达消费者手中.这样我们就可以看 ...

  5. (三)ActiveMQ之发布- 订阅消息模式实现

    一.概念 发布者/订阅者模型支持向一个特定的消息主题发布消息.0或多个订阅者可能对接收来自特定消息主题的消息感兴趣.在这种模型下,发布者和订阅者彼此不知道对方.这种模式好比是匿名公告板.这种模式被概括 ...

  6. JS 设计模式八 -- 发布订阅者模式

    概念 发布---订阅模式又叫观察者模式,它定义了对象间的一种一对多(一个发布,多个观察)的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象都将得到通知. 优点 1 ...

  7. 学习javascript设计模式之发布-订阅(观察者)模式

    1.发布-订阅模式又叫观察者模式,它定义对象之间一种一对多的依赖关系. 2.如何实现发布-订阅模式 2-1.首先指定好发布者 2-2.给发布者添加一个缓冲列表,用户存放回调函数以便通知订阅者 2-3. ...

  8. ionic3 发布订阅者模式实现

    在ionic3 中实现订阅发布模式,需要用到Events. Events下面有三个方法 events.subscribe()  订阅 events.publish()  发布 events.unsub ...

  9. 把酒言欢话聊天,基于Vue3.0+Tornado6.1+Redis发布订阅(pubsub)模式打造异步非阻塞(aioredis)实时(websocket)通信聊天系统

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_202 "表达欲"是人类成长史上的强大"源动力",恩格斯早就直截了当地指出,处在蒙昧时代即低 ...

随机推荐

  1. wait操作接口

    1.等待回收的两个函数wait()和waitpid()函数 1.1 wait(int *status)的用法:阻塞函数,等待任意一个子进程的返回.   *wait(NULL):对子进程的结束状态不关心 ...

  2. 吴裕雄--天生自然python学习笔记:python文档操作自动生成菜单 Word 文件

    许多学校营养午餐的菜单是由教师来轮流制作 ,这是一个 比较烦锁的工作,如 果能自动用教师最熟悉的 Word 文件来生成一个菜单文件,使教师对生成的菜单稍作 修改即可使用,那将是一个不错的主意. 案例要 ...

  3. es6变量和函数的提升、暂时性死区?

    es6变量和函数的提升.暂时性死区?

  4. Python-scapy学习

    scapy-arpspoof from scapy.all import Ether,ARP,sendp,getmacbyip Ether:用来构建以太网数据包 ARP:构建ARP数据包的类 send ...

  5. AngularJS中格式化日期为指定格式字符串

    var date = $filter('date')(new Date(),'MM/dd/yyyy');

  6. Java 的 LinkedList 的底层数据结构

    1. 数据结构--LinkedList源码摘要 public class LinkedList<E> extends AbstractSequentialList<E> imp ...

  7. [LC] 129. Sum Root to Leaf Numbers

    Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number ...

  8. 吴裕雄--天生自然Android开发学习:下载安装android stuio集成开发工具

    下载链接: https://developer.android.google.cn/index.html

  9. springmvc拦截器入门及其执行顺序源码分析

    springmvc拦截器是偶尔会用到的一个功能,本案例来演示一个较简单的springmvc拦截器的使用,并通过源码来分析拦截器的执行顺序的控制.具体操作步骤为:1.maven项目引入spring依赖2 ...

  10. jenkins发布项目到远程主机上,配置linux使用SSH免密码登录

    一.首先要配置两台linux如何使用SSH免密码登录,这样脚本执行scp命令以及远程执行脚本都不需要输入密码: A为本地主机(即用于控制其他主机的机器,jenkins服务器) ; B为远程主机(即被控 ...