1、定义程序员
在事件驱动的环境中,好比浏览器这种持续寻求用户关注的环境中,观察者模式(又名发布者-订阅者(publisher-subscripber)模式)是一种管理人与其任务之间的关系(确切地讲,是对象及其行为和状态之间的关系)的得力工具.用JavaScript的话来讲,这种模式的实质就是你能够对程序中某个对象的状态进行观察,而且在其发生改变时可以获得通知。编程
2、例子数组
咱们须要一个发布者的构造函数,它为该实例定义了一个类型为数组的属性,用来保存订阅者的引用。浏览器
function Publisher() { this.subscribers = []; }
接下来,构建订阅方法。全部Publisher实例都应该可以投送数据。只要把deliver方法添加到Publisher的prototype中,它就可以被全部Publisher对象共享。函数
// 订阅者订阅能力 Function.prototype.subscribe = function(publisher) { var that = this, alreadyExists = false, i, len = publisher.length; for(i = 0; i < len; i++) { if (el === this) { alreadyExists = true; } } if (!alreadyExists) { publisher.subscribers.push(this); } return this; }; // 订阅者具备退订能力 Function.prototype.unSubscribe = function(publisher) { var that = this, array = [], len = publisher.length; for(i = 0; i < len; i++) { if (el !== this) { array.push(this); } } publisher.subscribers = array; return this; };
应用之——工具
// 订阅者订阅能力 Function.prototype.subscribe = function(publisher) { var that = this, alreadyExists = false, i, len = publisher.length; for(i = 0; i < len; i++) { if (el === this) { alreadyExists = true; } } if (!alreadyExists) { publisher.subscribers.push(this); } return this; }; // 订阅者具备退订能力 Function.prototype.unSubscribe = function(publisher) { var that = this, array = [], len = publisher.length; for(i = 0; i < len; i++) { if (el !== this) { array.push(this); } } publisher.subscribers = array; return this; };
3、现实世界中的观察者性能
在现实世界中,观察者模式对于那种由许多JavaScript程序员合做开发的大型应用程序特别有用。它能够提升API的灵活性,使并行开发的多个市县可以彼此独立的进行修改。做为开发人员,你能够对本身的应用程序中什么是“使人感兴趣的时刻”作出决定。你所能监听的再也不只是click、load、blur和mouseover等浏览器事件。在富用户界面应用程序中,drag(拖动)、drop(拖放)、moved(移动)、complete(完成)和tabSwitch(标签切换)均可能是使人感兴趣的事件。它们都是在普通浏览器事件的基础上抽象出来的可观察事件,可由发布者对象向其监听者广播。this
在DOM脚本编程环境中的高级时间模式中,事件监听器说到底就是一种内置的观察者。事件处理器(handler)与事件监听器(listener)并非一回事。前者说穿了就是一种把事件传递给与其关联的函数的手段。并且在这种模型中一种事件只能指定一个回调方法。而在监听器模式中,一个事件能够与几个监听器关联。每一个监听器都能独立于其余监听器而改变。spa
// 使用事件监听器,可让多个函数响应同一个事件 var element = $('#example'); var fn1 = function(e) { // handle clikc }; var fn2 = function(e) { // do other stuff with click }; // 因为使用的是事件监听器,因此click事件发生时fn1和fn2都会被调用 addEvent(element, 'click', fn1); addEvent(element, 'click', fn2); // 但用事件处理器就办不到 var element = $('#example'); var fn1 = function(e) { // handle clikc }; var fn2 = function(e) { // do other stuff with click }; element.onclick = fn1; // 第二个onclick赋值的结果是fn1被fn2取代,所以click事件发生时只会调用fn2。 element.onclick = fn2;
监听器和观察者之间的共同之处显而易见。实际上它们互为同义词。它们都订阅特定的事件,而后等待事件的发生。事件发生时,订阅方的回调函数会获得通知。传给它们的参数是一个事件对象,其中包含着事件发生时间、事件类型和事件发源地等有用的信息。prototype
4、优点
观察者模式能够削减为事件注册监听器的次数,让可观察对象借助一个事件监听器替你处理各类行为并将信息委托给它的全部订阅者,从而下降内存消耗和提升互动性能,提升程序的可维护性。
5、劣势
使用这种观察者接口的一个不利之处在于建立可观察对象所带来的加载时间开销。这能够经过惰性加载技术加以化解。
6、小结
一个事件能够被5个订阅者订阅,而一个订阅者也能够订阅5个不一样的事件。对于浏览器这类互动环境来讲这很是理想。如今的Web应用程序愈来愈大,在此背景下,做为一种提升代码的可维护性和简洁性的有力手段,可观察对象的做用更显突出。