手撕观察者模式

akino ... 2021-10-04 设计模式
  • 观察者模式
小于 1 分钟

# 简述

观察者模式指的是一个目标对象被多个观察者对象监听,当目标对象监听的属性发生变化时,主动向观察者发送通知。

# 实现

# ES5

ES5 可以通过Object.defineProperty来设置setget进行拦截来实现该模式。

# 代码

var observedObj = { _no: 1 };
var observerObj = { _no: 1 };

function observer(oldVal, newVal) {
    console.log('observed的no属性值变为' + newVal);
    observer._no = newVal;
}

Object.defineProperty(observedObj, 'no', {
    set: function(newVal) {
        observer(this._no, newVal);
        this._no = newVal;
    },
    get: function() {
        return this._no;
    },
});

observedObj.no = 2;
console.log('observedObj: ', observedObj, '\nobserverObj: ', observerObj);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 输出

observedObj的no属性值变为2
observedObj:  { _no: 2 }
observerObj:  { _no: 2 }
1
2
3

# ES6

使用 ES6 新特性 Proxy 和 Reflect 结合使用监听对象属性

# 代码

class Obj {
    constructor(no) {
        this.no = no;
    }
}

var observedObj = new Obj(1);
var observerObj = new Obj(1);

const handler = {
    set: function(observed, key, value) {
        if (key === 'no') {
            observer(key, observed[key], value);
        }
        Reflect.set(observed, key, value);
    },
};

var observerProxy = new Proxy(observedObj, handler);

function observer(key, oldVal, newVal) {
    console.log(`observedObj的no属性值由${oldVal}变为${newVal}`);
    observerObj[key] = newVal;
}

observerProxy.no = 2;
console.log('observedObj: ', observedObj, '\nobserverObj: ', observerObj);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 输出

observedObj的no属性值由1变为2
observedObj:  Obj { no: 2 }
observerObj:  Obj { no: 2 }
1
2
3