介绍

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

示例

  • 订报纸
  • 订牛奶

UML类图

点击查看【processon】

代码

  1. // 保存所有状态,状态变化后触发所有观察者对象
  2. class Subject {
  3. constructor() {
  4. this.state = 0
  5. this.observers = []
  6. }
  7. getState() {
  8. return this.state
  9. }
  10. setState(state) {
  11. this.state = state
  12. this.notifyAllObservers()
  13. }
  14. attach(observer) {
  15. this.observers.push(observer)
  16. }
  17. notifyAllObservers() {
  18. this.observers.forEach(observer => {
  19. observer.update()
  20. })
  21. }
  22. }
  23. // 观察者
  24. class Observer {
  25. constructor(name, subject) {
  26. this.name = name
  27. this.subject = subject
  28. this.subject.attach(this)
  29. }
  30. update() {
  31. console.log(`name:${this.name} update, state: ${this.subject.getState()}`);
  32. }
  33. }
  34. // test
  35. const s = new Subject()
  36. const o1 = new Observer('o1', s)
  37. const o2 = new Observer('o2', s)
  38. const o3 = new Observer('o3', s)
  39. s.setState(1)

场景

  • 网页事件绑定 ```html

  1. - Promise
  2. - jquery callbacks
  3. - nodejs 自定义事件
  4. - EventEmitter
  5. ```javascript
  6. const EventEmitter = require('events').EventEmitter
  7. const events = new EventEmitter()
  8. // 监听 some 事件
  9. events.on('some', info => {
  10. console.log('fn1', info)
  11. })
  12. // 监听 some 事件
  13. events.on('some', info => {
  14. console.log('fn2', info)
  15. })
  16. // 触发 some 事件
  17. events.emit('some', 'xxxxxx')
  1. const EventEmitter = require('events').EventEmitter
  2. class Dog extends EventEmitter {
  3. constructor(name) {
  4. super()
  5. this.name = name
  6. }
  7. }
  8. let dog = new Dog('dog1')
  9. dog.on('bark', (name) => {
  10. console.log(name, 'bark-1')
  11. })
  12. dog.on('bark', (name) => {
  13. console.log(name, 'bark-2')
  14. })
  15. setInterval(() => {
  16. dog.emit('bark', 'ss')
  17. }, 1000)
  • Stream ```javascript const fs = require(‘fs’) const path = require(‘path’)

const stream = fs.createReadStream(path.resolve(__dirname, ‘../release/bundle.js’))

let length = 0 stream.on(‘data’, (chunk) => { let len = chunk.toString().length console.log(‘len’, len); length += len }) stream.on(‘end’, () => { console.log(‘length’, length); })

  1. - readline
  2. ```javascript
  3. const readline = require('readline')
  4. const fs = require('fs')
  5. const path = require('path')
  6. const rl = readline.createInterface({
  7. input: fs.createReadStream(path.resolve(__dirname, '../package-lock.json'))
  8. })
  9. let lineNum = 0
  10. rl.on('line', (line) => {
  11. lineNum++
  12. })
  13. rl.on('close', () => {
  14. console.log('lineNum', lineNum)
  15. })
  • nodejs中处理http请求(post),多进程通信(child_process)
  • vue,react组件生命触发
  • vue的watch

设计原则验证

  • 主题和观察者分离,不是主动触发,而是被动监听,两者解耦
  • 符合OCP