本系列文章来源于《Javascript设计模式》(张容铭版),做一个记录。
最近在学习《Javascript设计模式》一书,对学习过程做一个笔记总结。系列文章大家可以关注我的个人博客会不定时更新,大家一起学习一起进步。
概念
观察者模式:又称为发布-订阅者模式或者消息机制(妈蛋叫什么不重要主要是理解意思)。 首先我们需要把观察者创建出来,观察者模式有三部分,
- 消息容器
- 订阅消息方法
- 取消订阅的消息方法
- 发送订阅的消息方法
var Observer = (function () {
// 防止消息队列报漏而被篡改故将消息容器作为静态私有变量保存
var _messages = {};
return {
// 注册消息接口
register: function () {
},
// 发布消息接口
fire: function () {
},
// 移除消息接口
remove: function() {
}
}
}())
复制代码
现在我们来一一实现这三个方法,
register
register 的作用是将订阅者注册的消息推入到消息队列中,这里我们需要接收两个参数:消息的类型以及相应的处理动作,
// 注册消息接口
register: function (type, fn) {
// 消息不存在则创建一个该消息类型
if (typeof _messages[type] === 'undefined') {
_messages[type] = [fn];
} else { // 如果消息已经存在
_messages[type].push(fn);
}
}
复制代码
fire
fire 的作用是当观察者发布一个消息时将所有订阅者订阅的消息依次执行。所以这里要接收两个参数,消息类型以及动作执行时需要传递的参数(这里type是必须的)
// 发布消息接口
fire: function (type, args) {
// 如果该消息没有被注册,则返回
if (!_messages[type]) {
return;
}
// 定义消息信息
var events = {
type: type, // 消息类型
args: args || {} // 消息携带数据
},
len = _messages[type].length // 消息动作长度
// 遍历消息动作
for (var i =0 ; i < len; i++) {
// 依次执行注册的消息对应的动作序列
_messages[type][i].call(this, events);
}
}
复制代码
remove
remove 的方法是将订阅者注销的消息从消息队列中清除,这里我们也需要两个参数,即消息类型以及需要清除的动作。
// 移除消息接口
var Observer = (function () {
// 防止消息队列报漏而被篡改故将消息容器作为静态私有变量保存
var _messages = {};
return {
// 注册消息接口
register: function (type, fn) {
// 消息不存在则创建一个该消息类型
if (typeof _messages[type] === 'undefined') {
_messages[type] = [fn];
} else { // 如果消息已经存在
_messages[type].push(fn);
}
},
// 发布消息接口
fire: function (type, args) {
// 如果该消息没有被注册,则返回
if (!_messages[type]) {
console.log("没有注册该消息")
return;
}
// 定义消息信息
var events = {
type: type, // 消息类型
args: args || {} // 消息携带数据
},
i = 0, // 消息动作循环变量
len = _messages[type].length // 消息动作长度
// 遍历消息动作
for (; i < len; i++) {
// 依次执行注册的消息对应的动作序列
_messages[type][i].call(this, events);
}
},
// 移除消息接口
remove: function (type, fn) {
// 如果消息队列存在
if (_messages[type] instanceof Array) {
// 从最后一个消息动作遍历
var i = _messages[type].length - 1;
for (; i >= 0; i--) {
// 如果存在该动作则在消息动作序列中移除相应的动作
if (_messages[type][i] === fn) {
_messages[type].splice(i, 1);
console.log("删除成功")
} else {
console.log("删除失败不存在相应的动作")
}
}
} else {
console.log("消息不存在,无法移除")
}
}
}
}())
复制代码
现在我们来使用我们的代码
function test1(e) {
console.log("我是消息" + e.type, e.args.msg);
}
Observer.register('test1', test1)
Observer.fire('test1', {msg: '执行test1'})
Observer.fire('test2', {msg: '执行test1'})
Observer.remove('test1', function () {
})
Observer.remove('test1', test1)
// 我是消息test1 执行test1
// 没有注册该消息
// 删除失败不存在相应的动作
// 删除成功
复制代码
不得不说观察者模式思想真的还是很精妙的,又增强了我继续学习设计模式的信心。