最近在学习vue的双响数据绑定时,发现使用到观察者模式,但是我对于这种设计模式一知半解,所以特意总结下来。
基本定义
观察者设计模式定义了对象间的一种一对多的依赖关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。
观察者:
(Watcher)将自己注册到被观察对象(Dep)中,被观察对象将观察者存放在一个容器(Container)里。
被观察者:
被观察对象发生了某种变化,从容器中得到所有注册过的观察者,将变化通知观察者。
实现方式
观察者模式有很多实现方式,从根本上说,该模式必须包含两个角色:观察者和被观察对象。在刚才的例子中,业务数据是被观察对象,用户界面是观察者。观察者和被观察者之间存在“观察”的逻辑关联,当被观察者发生改变的时候,观察者就会观察到这样的变化,并且做出相应的响应。如果在用户界面、业务数据之间使用这样的观察过程,可以确保界面和数据之间划清界限,假定应用程序的需求发生变化,需要修改界面的表现,只需要重新构建一个用户界面,业务数据不需要发生变化。
代码示例
// 被观察者
function Dep () {
//存放观察者的容器
this.watchers = [];
let state = '';
// 获取
this.getState = function () {
return state;
};
// 设置
this.setState = function (value) {
if (state === value) {
return;
}
state = value;
// state变化时,发出通知
this.notice();
};
}
//添加观察者
Dep.prototype.addWatcher = function (watcher) {
let flag = false;
this.watchers.forEach(item => {
if (item === watcher) {
flag = true;
}
});
if (!flag) {
this.watchers.push(watcher);
}
}
// 删除观察者
Dep.prototype.removeWatcher = function (watcher) {
let _this = this;
_this.watchers.forEach((item,index) => {
if (item === watcher) {
_this.watchers.splice(index, 1);
}
});
}
//发出通知
Dep.prototype.notice = function () {
let _this = this;
_this.watchers.forEach(item => {
//观察者容器中,每一个观察者都会执行update方法
item.update(_this.getState());
});
}
// 观察者
function Watcher (name) {
this.name = name;
// 当被观察者的值改变时(setState()执行),观察者对象执行update方法
this.update = function (data) {
// do something
console.log(this.name + '接收到通知了:' + data);
}
}
// 创建被观察者实例对象
let dep = new Dep();
// 创建观察者实例对象, 2个
let watcher_a = new Watcher('a');
let watcher_b = new Watcher('b');
// 将观察者对象添加到被观察者的容器中
dep.addWatcher(watcher_a);
dep.addWatcher(watcher_b);
// 被观察者对象的值发生变化
dep.setState(1);
//输出结果:
//a接收到通知了:1
//b接收到通知了:1
参考资料
《javascript 设计模式》
JavaScript设计模式之观察者模式(学习笔记)