话不多说,直入主题:
原文档链接:javascript设计模式
例子:
// 订阅
document.body.addEventListener('click', function() {
console.log('click1');
}, false);
document.body.addEventListener('click', function() {
console.log('click2');
}, false);
// 发布
document.body.click(); // click1 click2
设计模式之订阅模式,实现订阅模式的简单代码:
// 观察者
var observer = {
// 订阅集合
subscribes: {},
// 订阅
subscribe: function(type, fn) {
if (!this.subscribes[type]) {
this.subscribes[type] = [];
}
// 收集订阅者的处理
typeof fn === 'function' && this.subscribes[type].push(fn);
},
// 发布 可能会携带一些信息发布出去
publish: function() {
var type = [].shift.call(arguments),
fns = this.subscribes[type];
// 不存在的订阅类型,以及订阅时未传入处理回调的
if (!fns || !fns.length) {
return;
}
// 挨个处理调用
for (var i = 0; i < fns.length; ++i) {
fns[i].apply(this, arguments);
}
},
// 删除订阅
remove: function(type, fn) {
// 删除全部
if (typeof type === 'undefined') {
this.subscribes = {};
return;
}
var fns = this.subscribes[type];
// 不存在的订阅类型,以及订阅时未传入处理回调的
if (!fns || !fns.length) {
return;
}
if (typeof fn === 'undefined') {
fns.length = 0;
return;
}
// 挨个处理删除
for (var i = 0; i < fns.length; ++i) {
if (fns[i] === fn) {
fns.splice(i, 1);
}
}
}
};
// 订阅岗位列表
function jobListForA(jobs) {
console.log('A', jobs);
}
function jobListForB(jobs) {
console.log('B', jobs);
}
// A订阅了笔试成绩
observer.subscribe('job', jobListForA);
// B订阅了笔试成绩
observer.subscribe('job', jobListForB);
// A订阅了笔试成绩
observer.subscribe('examinationA', function(score) {
console.log(score);
});
// B订阅了笔试成绩
observer.subscribe('examinationB', function(score) {
console.log(score);
});
// A订阅了面试结果
observer.subscribe('interviewA', function(result) {
console.log(result);
});
observer.publish('examinationA', 100); // 100
observer.publish('examinationB', 80); // 80
observer.publish('interviewA', '备用'); // 备用
observer.publish('job', ['前端', '后端', '测试']); // 输出A和B的岗位
// B取消订阅了笔试成绩
observer.remove('examinationB');
// A都取消订阅了岗位
observer.remove('job', jobListForA);
observer.publish('examinationB', 80); // 没有可匹配的订阅,无输出
observer.publish('job', ['前端', '后端', '测试']); // 输出B的岗位
回顾一下思路
定义一个全局的对象变量subscribes,这个将用来存储所有的需要来执行的事件方法,事件名
then 定义一个注册事件的方法subscribe(type, fn),参数分别是注册的事件名type,事件方法对象fn
then 以事件名为键值存储一个空数组 this.subscribes[type] = []
then 将fn存入 this.subscribes[type]的数组中,这样 当你注册一个click名的事件要执行回调方法fn时 便是
this.subscribes['type'] = []
this.subscribes['type'] .push(fn)
便能快速通过subscribes[click]找到要执行click时需要执行的方法,这便实现了一个事件订阅的过程
then 写了一个publish 便是通过输入事件名type找到要执行的方法 然后以此执行这个type键值里执行的所有的方法对象即可
for (var i = 0; i < this.subscribes[type].length; ++i) {
this.subscribes[type][i].apply(this, arguments);
}