继续设计模式,这次讲的是更为常用的发布订阅模式,又称为观察者模式。
一、什么是发布订阅模式
其实,我们常用的事件模型就是很好的发布订阅模式的例子。
document.getElementById('btn').addEventListener('click',function () { alert(); },false); // 模拟用户点击 // click
id是btn的按钮订阅了click事件,当用户点击按钮的时候,便会触发事件回调。
二、发布订阅的作用
发布订阅模式可以广泛用于异步编程中,我们无需关注对象在异步运行期间的内部状态。
发布订阅模式可以取代对象之间的通知机制,该模式可以让两个对象松耦合地联系在一起。
三、发布订阅模式的实现
1.基本实现
我们自己实现一个发布订阅模式:
var event = { eventList: [],add: function (name,fn) { if (!this.eventList[name]) { this.eventList[name] = []; } // 增加订阅事件队列 this.eventList[name].push(fn); },trigger: function () { var name = arguments[0],// 触发的事件名 args = Array.prototype.slice.call(arguments,1),fns = this.eventList[name]; // 出发执行的函数 if (!fns || 0 === fns.length) { // 没有订阅过该事件 return; } for (var i = 0,fn; fn = fns[i++]; ) { fn.apply(this,args) } } };
此时,我们可以对该对象增加对于的功能了:
// 增加open事件 event.add('open',function (a) { console.log(a); }); event.trigger('open','open');
2.取消订阅事件
event.remove = function (name,fn) { var fns = this.eventList[name]; if (!fns) { // 没有订阅的事件 return; } if (!fn) { // 没有传入具体的回调函数,取消所有的事件 fns && (fns.length = 0); } else { for (var i = fns.length - 1; i >= 0; --i) { var _fn = fns[i]; if (_fn === fn) { fns.splice(i,1); } } } }
event.remove(‘open’),这样我们就删除了前次发布的所有open事件。
四、总结
发布订阅模式的优势十分明显,一是时间上的解解耦,二是对象之间的解耦。并且在异步编程中帮我们完成松耦合的代码编写。当然问题也有,订阅的事件会一直存在内存中,而且过度使用的话,嵌套过深,定位问题的话,也会变得很复杂。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。