观察者模式和发布订阅区别

143 阅读2分钟

观察者模式

// 首先明白定义 观察则模式定义了一种 一对多的关系 多个观察者监听同一个目标对象,当这个目标对象发生变化时会通知所有的 观察者,观察则自动更新

// 所以在这里认为 这是两方的事情 是被观察者 和观察者 之间直接联系无中间者参与,还有就是 被观察者通知观察者的变化

abstract class Student {
    constructor(public teacher: Teacher) {

    }
    // 每个观察者都有一个update方法 用来在被观察对象更新的时候  执行更新或触发方法
    public abstract update(): void
}

class  Xueba extends Student {
    public update(): void {
        if (this.teacher.getState() === 'tiwen') {
            console.log(this.teacher.getState(), 'huidatiwen')
        }
    }
}

class Xuezha extends Student {
    public update (): void {
        if (this.teacher.getState() === 'tiwen') {
            console.log(this.teacher.getState(), 'ditibibi')
        }
    }
}
class Teacher {
    private state: string = 'jiangke'
    private students: Student[] = []
    public askQuestion () {
        this.state = 'laoshitiwen'
        this.notifyAllStudents()
    }
    getState() {
        return this.state
    }
    setState () {
        
    }
    attach (student: Student) {
        this.student.push(student)
    }
    notifyAllStudents () {
        this.students.forEach(student => student.update())
    }
}

let teacher = new Teacher ()
teacher.attach(new Xueba(teacher))
teacher.attach(new Xuezha(teacher))
teacher.askQuestion()  // 老师发生事件 状态变化 通知学生 (观察者)

// 在上边的例子中 老师中有 学生的数组, 学生中也有老师的实例 所以这里是关键

// 观察者常用的应用场景

  • // DOM事件绑定
  • // Promise
  • // callback
  • // 生命周期函数
  • // EvetBus
  • // Vue2响应式原理
  • // redux

发布订阅者模式

  • // 订阅者 把自己想 订阅的事情注册到 调度中心
  • // 发布者 把要发布的事件 发布到 调度中心
  • // 然后, 调度中心统一调度 订阅者注册到调度中心的代码

// 虽然 以上两种模式都有发布者和订阅者 ,但是观察者模式中调用是被观察者发布 而发布订阅者是有调度中心的 , 所以观察者模式 是发布和订阅者之间是相互知道的 但是发布订阅模式中是不知道的

// 下面的例子以 租房者 中介和 房东为例子

// 中介
class Agency {
    _topic = {} // envents

    subscirbe(type, listener) {
        let listeners = this._topic[type]
        if (listener) {
            listeners.push(listener)
        } else {
            this._topic[type] = [listener]
        }
    }
    publish (type, ...args) {
        let listeners = this._topic[type] || []
        listeners.forEach(listener => listener(...args))
    }
}

// 房东
class LandLord {
    constructor (public agency: Agency) {

    }
    // type 房子类型  area面积  money 房租价格
    lend(type, area, money) {
        this.agency.publish(type, area, money)
    }
}

// 房客
class Tenant {
    constructor (public angency: Angency, public name: string) {
        
    }
    order (type) {
        this.angency.subscirbe(type, (area, money) => {
            console.log(this.name, area + money)
        })
    }
}
// 搞一个中介
let angency = new Angency()
// 搞两个租客 
let rich = new Tenant(angency, 'rich')
let beipiao = new Tenant(angency, 'beipiao')
rich.order('haozhai')
beipiao.order('danjian')
// 搞一个房东
let landLord = new LandLord()
landLord.lend('haozhai', 1000, 100000)
landLord.lend('danjian', 10 ,2000)