liea

观察者模式(发布订阅模式)的实现方式及应用场景

简述

发布订阅模式的概念:当一个或多个对象依赖于某一个对象,当这个对象的状态发生改变,所有依赖于它的对象都得到状态改变的通知。

一个简单的示例:

// 主体
class Subject {
    constructor() {
        this.state = 0
        this.observers = []
    }
    getState() {
        return this.state
    }
    setState(state) {
        this.state = state
        this.notifyAllObservers()
    }
    notifyAllObservers() {
        this.observers.forEach(item => {
            item.update()
        })
    }
    attch(observer) {
        this.observers.push(observer)
    }
}

// 观察者
class Observer {
    constructor(name, subject) {
        this.name = name
        this.subject = subject
        this.subject.attch(this)
    }
    update() {
        console.log(`${this.name} update, state: ${this.subject.getState()}`)
    }
}

// 测试 这里创建了3个观察者
let s = new Subject()
let o1 = new Observer(\'o1\', s)
let o2 = new Observer(\'02\', s)
let o3 = new Observer(\'03\', s)

s.setState(1)
s.setState(2)
s.setState(3)

// 打印 
o1 update, state: 1
02 update, state: 1
03 update, state: 1
o1 update, state: 2
02 update, state: 2
03 update, state: 2
o1 update, state: 3
02 update, state: 3
03 update, state: 3

应用场景

  • 网页事件绑定

    • <button id="btn1">btn</button>
      <script>
          $(\'#btn1\').click(function(){ console.log(\'1\')})
          $(\'#btn1\').click(function(){ console.log(\'2\')})
          $(\'#btn1\').click(function(){ console.log(\'3\')})
      </script>
      // jquery中同一个对象 btn1,绑定多个click事件
      
  • Promise

  • jQuery callbacks(比较底层不常用)

    • // 可以理解为自定义事件或者自定义回调
      var callbacks = $.Callbacks()
      callbacks.add(function (info) {
          console.log(\'fn1\', info)
      })
      callbacks.add(function (info) {
          console.log(\'fn2\', info)
      })
      callbacks.add(function (info) {
          console.log(\'fn3\', info)
      })
      callbacks.fire(\'test1\')
      callbacks.fire(\'test2\')
      
  • node.js 自定义事件

    • // —————————示例1—————————————
      const EventEmitter = require(\'events\').EventEmitter
      const emitter = new EventEmitter
      emitter.on(\'some\', () => {
          // 监听 some 事件
          console.log(\'some event is occured 1\')
      })
      emitter.on(\'some\', () => {
          // 监听 some 事件
          console.log(\'some event is occured 2\')
      })
      emitter.on(\'some\', () => {
          // 监听 some 事件
          console.log(\'some event is occured 3\')
      })
      emitter.emit(\'some\')
      emitter.emit(\'some\', \'xiaoming\') // emit 可以传递参数过去
      
      
      // ---------示例2------------
      const EventEmitter = require(\'events\').EventEmitter
      // 任何构造函数都可以继承 EventEmitter 的方法 on emit
      class Person extends EventEmitter {
          constructor(name) {
              super()
              this.name = name
          }
      }
      const jack = new Person(\'jack\')
      jack.on(\'say\', function () {
          console.log(this.name, \'say\')
      })
      setInterval(() => {
          jack.emit(\'say\')
      }, 500)
      
      
      // ----------示例3---------------
      // 在读取一个体积比较大的文件,可以使用文件的流操作
      const fs = require(\'fs\')
      const readStream = fs.createReadStream(\'./data/filel.text\') // 读取文件的stream
      let length = 0
      readStream.on(\'data\', function(chunck) {
        length += chunck.toString().length
      })
      readStream.on(\'end\', function() {
        console.log(length)
      })
      

分类:

技术点:

相关文章:

  • 2021-12-28
  • 2022-01-08
  • 2021-05-23
  • 2021-12-18
  • 2021-12-18
  • 2020-11-08
  • 2021-12-28
猜你喜欢
  • 2021-11-12
  • 2021-06-09
  • 2021-05-18
  • 2021-11-24
  • 2021-09-11
  • 2022-12-23
  • 2021-09-27
相关资源
相似解决方案