美文网首页
观察者模式(发布订阅模式)

观察者模式(发布订阅模式)

作者: bounsail | 来源:发表于2021-05-18 21:58 被阅读0次

概念

观察者模式:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主体对象。这个主体对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。

观察者模式和发布订阅模式是有区别的
区别:观察者模式只有两个,一个是观察者一个是被观察者。发布订阅模式还有一个中间层,发布订阅模式的实现是,发布者通知给中间层 => 中层接受并通知订阅者 => 订阅者收到通知并发生变化
如下图所示:左边是观察者模式 —— 右边是发布订阅模式

11.png

举个栗子:
以学生为例,上课和下课的铃声就是被观察者,学生就是观察者,当下课铃声响了,学生就知道下课了,就出去跑着玩了,然后过了10分钟,上课铃声又响了,然后学生听到上课铃,又开始从外面往教室跑,去上课。

在DOM节点上绑定事件函数,JS和DOM之间就实现了一种观察者模式。

document.body.addEventListener("click", function() {
    alert("Hello World")
},false )
document.body.click() //模拟用户点击

以上js就是观察者,DOM就是被观察者,给DOM添加点击事件就相当于订阅了DOM,当DOM被点击,DOM就会通知js触发‘ alert("Hello World") ’

vue框架就采用了观察者模式,下面模仿vue的v-model双向绑定的实现:

利用Object.defineProperty实现

在ES5中主要是通过Object.defineProperty方法定义对象属性的设置和获取,并在进行设置时执行相关的处理函数

var targetObj = {      // 创建对象
    name:'小李'
}
var targetObj2 = {
    name:'小李'
}
function observer(oldVal, newVal) {  // 定义值改变时的处理函数(观察者)
    // 其他处理逻辑...
    targetObj2.name = newVal
    console.info('targetObj2的name属性的值改变为 ' + newVal);
}
// 定义name属性及其set和get方法(name属性为被观察者)
Object.defineProperty(targetObj, 'name', {
    enumerable: true,
    configurable: true,
    get: function() {
        return name;
    },
    set: function(val) {   
        observer(name, val)      //调用处理函数
        name = val
    }
});
targetObj.name = '张三';
targetObj.name = '李四';
console.log(targetObj2.name)

虽然只是改变了targetObj的name属性,但是因为观察者模式的设计,targetObj2的name属性同样被改变,这就实现了一个简单的观察者模式。

ES6 利用 class 实现

(也可改用利用原型prototype实现,原理相同)
实现派发事件,监听事件;

class TargetObj {
    constructor(age, name) {
        this.name = name;
        this.age = age;
    }
    set name(val) {
        observer(name, val);
        name = val;
    }
}
let targetObj = new TargetObj(1, 'Martin');
function observer(oldVal, newVal) {  // 定义值改变时的处理函数
    // 其他处理逻辑...
    console.info('name属性的值从 '+ oldVal +' 改变为 ' + newVal);
}
targetObj.name = 'Lucas';
console.info(targetObj)

使用Reflect和Proxy实现(参见vue3.0源码)

相关文章

网友评论

      本文标题:观察者模式(发布订阅模式)

      本文链接:https://www.haomeiwen.com/subject/subsjltx.html