Iwen's blog Iwen's blog
首页
  • 前端文章

    • JavaScript
    • Vue
  • 学习笔记

    • 《JavaScript教程》笔记
    • 《JavaScript高级程序设计》笔记
    • 《ES6 教程》笔记
    • 《Vue》笔记
    • 《TypeScript 从零实现 axios》
    • 小程序笔记
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • Linux
  • 学习
  • 面试
  • 心情杂货
  • 友情链接
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
复盘
关于

Iwen

不摸鱼的哥哥
首页
  • 前端文章

    • JavaScript
    • Vue
  • 学习笔记

    • 《JavaScript教程》笔记
    • 《JavaScript高级程序设计》笔记
    • 《ES6 教程》笔记
    • 《Vue》笔记
    • 《TypeScript 从零实现 axios》
    • 小程序笔记
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • Linux
  • 学习
  • 面试
  • 心情杂货
  • 友情链接
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
复盘
关于
  • Vue

  • Vue进阶

  • CSS

  • ES6

  • Base

  • Core

  • Array

  • Object

  • String

  • Async

  • Browser

  • Http

  • 性能优化

  • 正则

  • 经典总结

  • 设计模式

    • 单例模式
    • 策略模式
    • 观察者模式
      • 发布订阅模式
      • 观察者模式
      • 两者区别
    • 代理模式
    • 职责链模式
  • 数据结构

  • 算法

  • 手写

  • TypeScript

  • 复盘
  • 设计模式
Mr.w
2020-11-29

观察者模式

# 发布订阅模式(观察者模式)

发布—订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。
—— 来自《JavaScript设计模式与实践》

设计模式让人最有议论,或者说最让人模糊的,就是发布订阅模式和观察者模式了,这也是面试的一个考点。

不妨先来看一下~

# 发布订阅模式

适用于业务场景中当一个对象的状态发生变化时,需要自动通知其他关联对象,自动刷新对象状态,或者说执行对应对象的方法

比如你是一个老师,需要通知班里家长的时候,你可以建一个群(列表)。每次通知事件的时候只要群发到群里(循环执行这个列表就好了),而不用关心这个群里有谁,反正都是学生的家长。

实现流程:

  • 每一个观察者(Observer)都有一个update方法,并且观察者的状态就是等待被触发
  • 每一个主题(subject)都可以通过attach方法接纳N个观察者所观察,即观察者们存储在主题的observers数组里
  • 主题有初始化状态init、获取信息getMessage和设置信息setMassage三个通用型方法
  • 当主题的状态发生变化时,通过特定的notifyAllObervers方法通知所有观察者
// 创建一个主题,保存状态,状态变化之后触发所有观察者对象
class Subject {
    constructor() {
        this.message = '暂无通知';
        this.observers = [];    // 缓存需要通知的订阅者
    }
    // 获取信息
    getMessage() {  
        return this.message
    }
    // 设置信息
    setMassage(message) {
       this.message = message;
       this.notifyAllObservers()
    }
    // 发布通知
    notifyAllObservers() {  
        this.observers.forEach(observer => observer.update())
    }
    // 添加订阅者对象
    attach(observer) {  
       this.observers.push(observer)
    }
}

// 观察者
class Observer {
    constructor(name , message) {
       this.name = name;
       this.message = message;
       this.message.attach(this);
    }
    update() {
        console.log(`${this.name} 收到通知: ${this.message.getMessage()}`)
    }
}

// 创建班级群(主题 Subject)
let message = new Subject();

// 邀请家长进群(观察者 Observer)
let a = new Observer('张三', message);
let b = new Observer('李四', message);
let c = new Observer('王五', message);

// 发布信息
message.setMassage('明天开家长会')
message.setMassage('后天开始放假')
message.setMassage('在家也要好好学习')

// 张三 收到通知: 明天开家长会
// 李四 收到通知: 明天开家长会
// 王五 收到通知: 明天开家长会
// 张三 收到通知: 后天开始放假
// 李四 收到通知: 后天开始放假
// 王五 收到通知: 后天开始放假
// 张三 收到通知: 在家也要好好学习
// 李四 收到通知: 在家也要好好学习
// 王五 收到通知: 在家也要好好学习
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

主题每次改变状态后都会触发所有观察者状态更新,主题触发了3次状态,观察者一定update了9次。

# 观察者模式

# 两者区别

可以理解为(来自Github)

  • 观察者模式:没中间商赚差价
  • 发布订阅模式:有中间商赚差价
策略模式
代理模式

← 策略模式 代理模式→

最近更新
01
flex布局页面自适应滚动条问题
12-28
02
前后端分离开发请求接口跨域如何携带cookie的问题
12-28
03
怎么实现div长宽比固定width-height4比3
12-28
更多文章>
Theme by Vdoing | Copyright © 2017-2022 Iwen | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式