您的位置:首页 > Web前端 > JavaScript

原生JavaScript实现观察者模式

2017-10-19 17:37 561 查看

什么是观察者模式

维基百科对观察者模式的定义如下:

观察者模式是软件设计模式的一种。在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实时事件处理系统。

说的简单些,就是在数据发生改变时,对应的处理函数自动执行。维基的定义中涉及到了主动发出通知,按照这种方式,在angularJS中的事件广播更是中规中矩,但是其缺点是代码的可维护性较差。那么如果不进行主动通知,而是在进行对象属性值设置时,调用相关的处理函数,也可达到同等效果。如下见详细代码。

ES5下的实现

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

// 创建对象
var targetObj = {
age: 1
}
// 定义值改变时的处理函数
function observer(oldVal, newVal) {
// 其他处理逻辑...
console.info('name属性的值从 '+ oldVal +' 改变为 ' + newVal);
}

// 定义name属性及其set和get方法
Object.defineProperty(targetObj, 'name', {
enumerable: true,
configurable: true,
get: function() {
return name;
},
set: function(val) {
//调用处理函数
observer(name, val)
name = val;
}
});

targetObj.name = 'Martin';
targetObj.name = 'Lucas';
console.info('targetObj:', targetObj)


输出结果为

...
name属性的值从 Martin 改变为 Lucas
targetObj: {age: 1, name: 'Lucas'}
...


ES6的实现

使用set方法实现

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)


输出结果为

...
name属性的值从 Martin 改变为 Lucas
targetObj: {age: 1, name: 'Lucas'}
...


使用Reflect和Proxy实现

在ES6中新增的Proxy Api用处很多,结合Reflect Api可以方便的实现很多强大的逻辑,详细介绍可以参见《ECMAScript 6 入门》—— 阮一峰 中的介绍。实现代码如下:

class TargetObj {
constructor(age, name) {
this.name = name;
this.age = age;
}
}

let targetObj = new TargetObj(1, 'Martin');

let observerProxy = new Proxy(targetObj, {
set(target, property, value, reciever) {
if (property === 'name') {
observer(target[property], value);
}

Reflect.set(target, property, value, reciever);
}
});
// 定义值改变时的处理函数
function observer(oldVal, newVal) {
// 其他处理逻辑...
console.info(`name属性的值从 ${oldVal} 改变为 ${newVal}`);
}

observerProxy.name = 'Lucas';
console.info(targetObj);


输出结果为

...
name属性的值从 Martin 改变为 Lucas
targetObj: {age: 1, name: 'Lucas'}
...


总结

ES6中很多的新增功能,都有效的提升了JS本身的合理性和高效性

很多基础的方法,概念,虽然在做业务实现时使用较少,但是去了解其理念,对编码思想的影响是很大的

观察者模式可以很好的完成数据间的交互行为,虽然已经经常在用,但是具体了解后对整体的结构和原理有了更深层次的理解

Proxy真的很好,很强大
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  javascript 软件设计