观察者模式

◆ 发布&订阅
◆ 一对多

应用场景:
◆ 点咖啡,点好之后坐等被叫
◆ 网页事件绑定
◆ Promise
◆ jQuery callbacks
◆ nodejs自定义事件

观察者模式符合的设计原则:
◆ 主题和观察者分离,不是主动触发而是被动监听,两者解耦
◆ 符合开放封闭原则

1. 实现一个观察者

image.png
// 主题,接收状态变化,触发每个观察者
class Subject {
    constructor() {
        this.state = 0
        this.observers = []
    }
    getState() {
        return this.state
    }
    setState(state) {
        this.state = state
        this.notifyAllObservers()
    }
    attach(observer) {
        this.observers.push(observer)
    }
    notifyAllObservers() {
        this.observers.forEach(observer => {
            observer.update()
        })
    }
}

// 观察者,等待被触发
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()}`)
    }
}

// 测试代码
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)

2. 观察者的应用

2.1 网页事件绑定

$('#btn1').click(function () {
  console.log(1)
})
$('#btn1') .click(function () {
  console.log(2)
})
$('#btn1').click(function () {
  console.log(3)
})
// 1, 2, 3

2.2 promise.then

var src =' '
var result = loadImg(src)
result.then(function (img) {
  console.log('width', img.width)
  return img
}).then(function (img) {
  console.log('height', img.height)
})

2.3 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('gogogo') // fn1 gogogo fn2 gogogo fn3 gogogo
callbacks.fire('fire') // fng fire fn2 fire fn3 fire

2.4 node自定义事件

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事件
emitter.emit('some')

// 传递参数
const EventEmitter = require('events').EventEmitter
const emitter = new EventEmitter()
emitter.on('sbowName', name => {
  console. log('event occured', name)
})
emitter.emit('sbowName', 'zhangsan')

继承node中的观察者模式

const EventEmitter = require('events').EventEmitter
// 在自己的类中继承EventEmitter的观察者模式
class Dog extends EventEmitter {
  constructor(name) {
    super()
    this.name = name
  }
}
var simon = new Dog('simon')
simon.on( 'bark', function () {
  console.log(this.name, 'barked')
})
setInterval(() => {
  simon.emit('bark')
}, 500)

node中的处理流文件也是观察者模式

var fs = require('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)
))
var readline = require('readline');
var fs = require('fs')
var rl = readline.createInterface({
  input: fs.createReadStream('./data/file1.txt')
});
var lineNum = 0
rl.on('line', function(line){
  lineNum++
});
rl.on('close', function() {
console.log('lineNum' , lineNum)
});

node读取请求参数

function serverCallback(req, res) {
  var method = req.method.toLowerCase() //获取请求的方法
  if (method === '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()
    })
  }
}
image.png

你可能感兴趣的:(观察者模式)