觀察者模式(發布訂閱模式)的實現方式及應用場景


觀察者模式(發布訂閱模式)的實現方式及應用場景

簡述

發布訂閱模式的概念:當一個或多個對象依賴於某一個對象,當這個對象的狀態發生改變,所有依賴於它的對象都得到狀態改變的通知。

一個簡單的示例:

// 主體
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)
      })
      


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM