Javascript 设计模式系统讲解与应用——学习笔记8-观察者模式

观察者模式

  • 发布 & 订阅
  • 一对多

示例:

  • 点咖啡,点好之后坐等被叫

在这里插入图片描述

简化之后的UML类图
在这里插入图片描述

// 主题 保存状态,状态变化之后触发所有观察者对象
class Subject {
  constructor() {
    this.state = 0
    this.observers = []
  }
  getState () {
    return this.state
  }
  setState(state) {
    this.state = state
    this.notifyAllObservers()
  }
  notifyAllObservers() {
    this.observers.forEach(observer => {
      observer.update()
    })
  }
  attach(observer) {
    this.observers.push(observer)
  }
}


// 观察者
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}`)
  }
}

// test
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)
场景1 jQuery
网页事件绑定
<button id="btn1">btn</button>
<script>
  $('#btn1').click(funciton () {
    console.log(1)
  })
  $('#btn1').click(funciton () {
    console.log(2)
  })
  $('#btn1').click(funciton () {
    console.log(3)
  })
</script>
Promise
const src = 'https://xxxx.png'
const result = loadImg(src)

result.then(funciton (img) {
  console.log('width', img.width)
  return img
}).then(function (img) {
  console.log('height', img.height)
})

jQuery callbacks
const callbacks = $.Callbacks()
callbacks.add(function(info) {
  console.log('fn1', info)
})
callbacks.add(funciton(info) {
  console.log('fn2', info)
})
callbacks.add(funciton(info) {
  console.log('fn3', info)
})

callbacks.fire('hello')
callbacks.fire('world')
场景2
nodejs自定义事件

const EventEmitter = require('events').EventEmitter
const emitter1 = new EventEmitter()

// 使用1
emitter1.on('some', () => {
  console.log('监听some事件1')
})
emitter1.on('some', () => {
  console.log('监听some事件2')
})
// 触发some事件
emitter1.emit(some)

// 使用2
emitter1.on('getName', name => {
  console.log(name)
})
emitter1.emit('getName', '小白')  // emit传递参数过去

// 使用3 继承
// 任何构造函数都可以继承 EventEmitter的方法, on  emit
class Dog extends EventEmitter {
  constructor(name) {
    super()
    this.name = name
  }
}
const simon = new Dog('simon')
simon.on('bark', function() {
  console.log(this.name, ' barked')
}
setInterval(() => {
  simon.emit('bark')
}, 500)

// Stream 用到了自定义事件
const fs = require('fs')
// 读取文件的stream 流
const readStream = fs.createReadStream('./data/file1.txt')
const length = 0
// 一点点读数据,监听
readStream.on('data', function() {
  length += chunk.toString().length
})
readStream.on('end', function() {
  console.log(length)
})

// readline 用到了自定义事件
const readline = require('readline')
const rl = readline.createInterface({
  input: fs.createReadStream('./data/file1.txt')
})
const lineNum = 0
rl.on('line', funciton (line) {
  lineNum ++
})
rl.on('close', function() {
  console.log('lineNum', lineNum)
})
其他场景
  • nodejs中:处理http请求;多进程通讯;
    http请求
function serverCallback(req, res) {
  const method = req.method.toLowerCase() // 获取请求方法
  if (method === 'get') {
    // 处理get请求代码
  }
  if (method === 'post') {
    // 接收post请求内容
    let data = ''
    req.on('data', function (chunk) {
      // 一点点接收
      data += chunk.toString()
    })
    req.on('end', funciton () {
      // 接收完毕,将内容输出
      res.writeHead(200, {'Content-type': 'text/html'})
      res.write(data)
      res.end()
    })
  }
}

多进程通讯

// parent.js
const cp = require('child_process')
const n = cp.for('./sub.js')
n.on('message', (m) => {
  console.log(`Parent got message: ${m}`)
})
n.send({hello: 'workd'})

// sub.js
process.on('message', m => {   // 监听信息
  console.log(`Child got message: ${m}`)
})
process.send({foo: 'bar'})     // 发送信息
  • Vue和React组件生命周期触发
  • vue watch
设计原则验证
  • 主题和观察者分离,不是主动触发而是被动监听,两者解耦
  • 符合开放封闭原则
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神小夜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值