设计模式:发布订阅 & 观察者

72 阅读1分钟

发布订阅模式

// 定义
function EventEmitter() {
    this._events = {}
}
EventEmitter.prototype.on = function(eventName, cb){
    if(!this._events[eventName])this._events[eventName]=[]
    this._events[eventName].push(cb)
}
EventEmitter.prototype.emit = function(eventName, ...args){
    if(this._events[eventName]){
        this._events[eventName].forEach(cb=>cb(...args))
    }
}
EventEmitter.prototype.off = function(eventName, cb){
    if(this._events[eventName]){
        this._events[eventName] = this._events[eventName].filter(item=>(item!==cb&&item.cb!==cb))
    }
}
EventEmitter.prototype.once = function(eventName, cb){
    const once = (...args) => {
        cb(...args)
        this.off(eventName, once)
    }
    once.cb = cb
    this.on(eventName, once)
}
// 使用
const emitter = new EventEmitter()
emitter.on('data', (data)=>{console.log(data)})
emitter.emit('data','data1')
emitter.once('data','data2')

观察者模式

// 定义
class Subject {
    deps: Array<Observer>;
    state: Number;
    constructor() {
        this.deps = []
        this.state = 0
    }
    attach(obs: Observer) {
        this.deps.push(obs)
    }
    setState(num: Number) {
        this.state = num
        this.notifyAllObserver();
    }
    notifyAllObserver() {
        this.deps.forEach(obs => {
            obs.run(this.state)
        })
    }
}
abstract class Observer {
    subject: Subject;
    constructor(subject: Subject) {
        this.subject = subject
        this.subject.attach(this)
    }
    abstract run(data: String|Number):void
}
class BinaryObserver extends Observer {
    constructor(subject: Subject){
        super(subject)
    }
    run(data: String|Number):void{
        console.log('binary observer:', dataÏ)
    }
}
// 使用
const sub = new Subject()
const o1 = new BinaryObserver(sub)


sub.setState(100)

发布订阅 与 观察者的区别

  • 发布订阅模式无耦合,观察者模式有耦合
  • 发布订阅模式手动触发回调函数,观察者模式根据依赖的变化触发副作用函数
  • 发布订阅重点在我要干什么,观察者模式重点在我干了这件事会带来什么影响