观察者模式和发布订阅模式的区别

Crq
Crq
Crq
324
文章
0
评论
2021年5月2日05:06:51
评论
415 1539字阅读5分7秒
摘要

之前一直对观察者模式和发布订阅模式的区别理解不深,正好这段时间在看vue源码的分析,vue数据双向绑定也用到了发布订阅模式,于是又把这两者探究了一番,今天做个笔记加强印象。

观察者模式和发布订阅模式最大的区别就是发布订阅模式有个事件调度中心。

从图中可以看出,观察者模式中观察者和目标直接进行交互,而发布订阅模式中统一由调度中心进行处理,订阅者和发布者互不干扰。这样一方面实现了解耦,还有就是可以实现更细粒度的一些控制。比如发布者发布了很多消息,但是不想所有的订阅者都接收到,就可以在调度中心做一些处理,类似于权限控制之类的。还可以做一些节流操作。

接下来看一下代码实现
观察者模式:

// 观察者
class Observer {
constructor() {
}
update(val) {
}
}
// 观察者列表
class ObserverList {
constructor() {
this.observerList = []
}
add(observer) {
return this.observerList.push(observer);
}
remove(observer) {
this.observerList = this.observerList.filter(ob => ob !== observer);
}
count() {
return this.observerList.length;
}
get(index) {
return this.observerList[index];
}
}
// 目标
class Subject {
constructor() {
this.observers = new ObserverList();
}
addObserver(observer) {
this.observers.add(observer);
}
removeObserver(observer) {
this.observers.remove(observer);
}
notify(...args) {
let obCount = this.observers.count();
for (let index = 0; index

发布订阅模式:

class PubSub {
constructor() {
this.subscribers = {}
}
subscribe(type, fn) {
if (!Object.prototype.hasOwnProperty.call(this.subscribers, type)) {
this.subscribers[type] = [];
}
this.subscribers[type].push(fn);
}
unsubscribe(type, fn) {
let listeners = this.subscribers[type];
if (!listeners || !listeners.length) return;
this.subscribers[type] = listeners.filter(v => v !== fn);
}
publish(type, ...args) {
let listeners = this.subscribers[type];
if (!listeners || !listeners.length) return;
listeners.forEach(fn => fn(...args));
}
}
let ob = new PubSub();
ob.subscribe('add', (val) => console.log(val));
ob.publish('add', 1);

从上面代码可以看出,观察者模式由具体目标调度,每个被订阅的目标里面都需要有对观察者的处理,会造成代码的冗余。而发布订阅模式则统一由调度中心处理,消除了发布者和订阅者之间的依赖。

观察者模式跟我们平时用的事件也有一定的关系,比如:

ele.addEventListener('click', () => {});

addEventListener就相当于注册了一个观察者,当观察到‘click’事件的时候,作出一些处理。

weinxin
我的微信
这是我的微信扫一扫
Crq
  • 本文由 发表于 2021年5月2日05:06:51
  • 转载请注明:https://www.cncrq.com/9160.html
Linux下如何实现与Internet时间同步 Linux教程

Linux下如何实现与Internet时间同步

关于时区的概念,其实初中地理课已经涉及,很多人都多少了解一些,可能只是细节搞不太清楚。为什么会将地球分为不同时区呢?因为地球总是自西向东自转,东边总比西边先看到太阳,东边的时间也总...
老炮儿教你在 Debian Linux上配置网桥 Linux教程

老炮儿教你在 Debian Linux上配置网桥

如何你想为你的虚拟机分配 IP 地址并使其可从你的局域网访问,则需要设置网络桥接器。默认情况下,虚拟机使用 KVM 创建的专用网桥。但你需要手动设置接口,避免与网络管理员发生冲突。
linux下安装python3.5.3的方式 Linux教程

linux下安装python3.5.3的方式

Python是一种面向对象的解释型计算机程序设计语言。Python具有丰富和强大的库。它常被昵称为胶水语言,能够把用其他语言制作的各种模块(尤其是C/C++)很轻松地联结在一起。那...
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: