观察者模式

观察者模式

1. 介绍

  • 发布订阅
  • 一对一(多)

2. UML 演示

在这里插入图片描述

3. 代码演示

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

//状态变化之后触发所有观察者对象
class Subject {
  constructor() {
    this.observers = []
    this.state = 0
  }

  getState() {
    return this.state
  }

  setState(state) {
    this.state = state
    this.notifyAllObservers()
  }
  notifyAllObservers() {
    this.observers.forEach(observer => {
      observer.update()
    })
  }
  attach(observer) {
    this.observers.push(observer)
  }
}

//测试
let s = new Subject()
let o1 = new Observer('o1', s)
let o2 = new Observer('o2', s)
let o3 = new Observer('o3', s)

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

4. 场景

4.1 网页事件绑定

<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>

4.2 Promise

function loadImg(src) {
  let promise = new Promise(function(resolve, reject) {
    let img = document.createElement('img')
    img.onload = function() {
      resolve(img)
    }
    img.onerror = function() {
      reject('图片加载失败')
    }
    img.src = src
  })
  return promise
}

let src = '//img.mukewang.com/5bc45ce20001976409360316.jpg'
let result = loadImg(src)

result
  .then(function(img) {
    alert(`width:${img.width}`)
  })
  .then(function(img) {
    alert(`height:${img.height}`)
  })
  .catch(function(ex) {
    alert(ex)
  })

4.3 jQuery callbacks

var callbacks = $.Callbacks() //注意大小写
callbacks.add(function(info) {
  console.log('f1n', info)
})
callbacks.add(function(info) {
  console.log('fn2', info)
})
callbacks.add(function(info) {
  console.log('fn3', info)
})
callbacks.fire('gogogo')
callbacks.fire('fire')

4.4 nodejs 自定义事件

  • emitter

    const EventEmitter = require('events').EventEmitter
    const emitter1 = new EventEmitter()
    
    emitter1.on('some', () => {
      //监听some事件
      console.log('some event is occured 1')
    })
    emitter1.on('some', () => {
      //监听some事件
      console.log('some event is occured 2')
    })
    //触发some事件
    emitter1.emit('some')
    
  • emit 中传递参数

    const EventEmitter = require('events').EventEmitter
    const emitter = new EventEmitter()
    
    emitter.on('some', name => {
      //监听some事件
      console.log('some event', name)
    })
    eemitter.emit('some', 'zhangsan') //emit中可以传递参数
    
  • 任何构造函数都可以继承 EventEmitter 的方法(on、emit)

    const EventEmitter = require('events').EventEmitter
    
    class Dog extends EventEmitter {
      constructor(name) {
        super()
        this.name = name
      }
    }
    
    var simon = new Dog('simon')
    simon.on('bark', function() {
      console.log(this.name, 'braked')
    })
    setInterval(() => {
      simon.emit('bark')
    }, 500)
    
  • Stream

    var fs = retuqire('fs')
    var readStream = fs.createReadStream('.data/file1.txt/') //读取文件的stream
    
    var length = 0
    readStream.on('data', function(chunk) {
      length += chunk.toString().length
    })
    
    readStream.on('end', function() {
      console.log(length)
    })
    
  • readline 用到了自定义事件

    const fs = require('fs')
    const readline = require('readline')
    
    let rl = readline.createInterface({
      input: fs.createReadStream('./data/file1.txt')
    })
    let lineNum = 0
    rl.on('line', function(line) {
      lineNum++
    })
    rl.on('close', function() {
      console.log('lineNum', lineNum)
    })
    
  • nodejs 中:处理 http 请求;多进程通讯

    function serverCallback(req, res) {
      var method = req.method.toLowerCase() //获取请求方法
      if (method === 'get') {
        //上文代码示例中处理GET请求的代码
      }
      if (method === 'post') {
        //接受post请求的内容
        var data = ''
        req.on('data', function(chunk) {
          //一点一点的接受内容
          data += chunk.toString()
        })
        req.on('end', function() {
          //接受完毕,将内容输出
          res.writeHead(200, {
            'Content-type': 'text/html'
          })
          res.write(data)
          res.end()
        })
      }
    }
    
  • vue 和 react 组件生命周期触发

  • vue watch

5. 设计原则

  • 主题和观察者分离,不是主动触发而是被动监听,两者解耦
  • 符合开放封闭原则
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值