JavaScript 常见设计模式----观察者模式

84 阅读1分钟

UML类图:

image.png

示例代码

// 主题
class Subject {
    private state: number = 0
    private observers: Observer[] = []

    getState(): number {
        return this.state
    }

    setState(newState: number) {
        this.state = newState
        this.notify() // 通知
    }

    // 添加观察者
    attach(observer: Observer) {
        this.observers.push(observer)
    }

    // 通知
    private notify() {
        this.observers.forEach(observer => {
            observer.update(this.state)
        })
    }
}

// 观察者
class Observer {
    name: string
    constructor(name: string) {
        this.name = name
    }
    update(state: number) {
        console.log(`${this.name} updated, state is ${state}`)
    }
}

const sub = new Subject()
const observer1 = new Observer('A')
sub.attach(observer1)
const observer2 = new Observer('B')
sub.attach(observer2)

sub.setState(1)

是否符合设计原则?

  • Observer 和 Subject分离,解耦
  • Observer可自由扩展
  • Subject可自由扩展

观察者模式使用场景

  • DOM事件
  • Vue React 组件生命周期
  • Vue watch
  • Vue 组件更新过程
  • 各种异步回调(setTimeOut/setInterval/Promise.then)
  • MutationObserver

观察者模式VS发布订阅模式

发布订阅模式不属于传统的23种设计模式 是观察者模式的另一种实现

image.png

image.png 区别

  • 观察者:Subject和Observer 直接绑定,中间无媒介
  • 发布订阅:Publisher和Observer互不相识,中间有媒介

场景

  • 1.自定义事件

image.png

mitt image.png

event-emitter

image.png

  • 2.postMessage通讯

image.png

iframe通讯 main发送 image.png main:接收

image.png child接收

image.png child发送:

image.png

注意事项:自定义事件要及时Off

  • 组件销毁之前off,避免内存泄露
  • off时要传入之前的函数(而非匿名函数)