理解观察者模式
观察者的使用场合就是:当一个对象的改变需要同时改变其它对象,并且它不知道具体有多少对象需要改变的时候,就应该考虑使用观察者模式。先看官网的demo这个例子,涉及到了 add 与 fire方法,熟悉设计模式的童鞋呢,一眼就能看出,其实又是基于发布订阅(Publish/Subscribe)的观察者模式的设计。
var Observable = { callbacks: [], add: function(fn) { this.callbacks.push(fn); }, fire: function() { this.callbacks.forEach(function(fn) { fn(); }) } }
使用add开始订阅:
Observable.add(function() { alert(1) }) Observable.add(function() { alert(2) })
使用fire开始发布:
Observable.fire(); // 1, 2
设计的原理:
开始构建一个存放回调的数组,如this.callbacks= []
添加回调时,将回调push进this.callbacks,执行则遍历this.callbacks执行回调,也弹出1跟2了。当然这只是简洁的设计,便于理解,整体来说设计的思路代码都是挺简单的,那么我们从简单的设计深度挖掘下这种模式的优势。
注意:如果没有做过复杂交互设计,或者大型应用的开发者,可能一开始无法理解这模式的好处,就简单的设计而言用模式来处理问题,有点把简单的问题复杂化。我们不是为了使用模式而使用的。
组件开发为了保证组件可以在不同的项目中都适用,其必须是对其常用功能抽象出来加以实现,绝不会包含具体的业务逻辑而某一特定的项目使用者在其业务场景中使用组件时不可避免的要加入不同场景的业务逻辑。
实际运用:
在进行组件开发中,为了保证组件可以在不同的类似项目场景中都能适用,那么就必须是对其常用功能抽象出来加以实现。
我们来看看具体的实际用处:
假设一段ajax的请求,成功后通过done返回结果数据:
$.ajax({ url: "test.html", context: document.body }).done(function(data) { //data数据的处理 $('aaron1').html(data.a) $('aaron2').html(data.b) $('aaron3').html(data.c) //其余处理 });
咋一看好像都挺好,没什么问题,但是仔细观察我们会发现所有的逻辑是不是都写在done方法里面,这样确实是无可厚非的,但是问题就是逻辑太复杂了。Done里面有数据处理、html渲染、还可能有其它不同场景的业务逻辑。这样如果是换做不同的人去维护代码,增加功能就会显得很混乱而且没有扩展性。那么观察者模式能很好的解决了这个的问题。
我们优化下代码:
$.ajax({ url: "test.html", context: document.body }).done(function(data) { pocessData() pocessHtml() pocessOther() } function pocessData() { //处理数据 } function pocessHtml() { $('aaron1').html(data.a) $('aaron2').html(data.b) $('aaron3').html(data.c) } function pocessOther() { //处理其他逻辑 }
这种方式的好处是,分离出各种的业务函数,从而降低了代码之间的耦合度,但是这样代码写法几乎就是“就事论事”的处理,达不到抽象复用。
那么我们用之前的观察者模式加工一下上面的代码:(这只是伪代码,用于理解)
Observable.add(function() { //pocessData }) Observable.add(function() { $('aaron1').html(data.a) $('aaron2').html(data.b) $('aaron3').html(data.c) }) Observable.add(function() { //pocessOther }) $.ajax({ url: "test.html", context: document.body }).done(function(data) { Observable.fire(data) })
设计该模式背后的主要动力是促进形成松散耦合。在这种模式中,并不是一个对象调用另一个对象的方法,而是一个对象订阅另一个对象的特定活动并在状态改变后获得通知。订阅者也称为观察者,而被观察的对象称为发布者或主题。当发生了一个重要的事件时,发布者将会通知(调用)所有订阅者并且可能经常以事件对象的形式传递消息。
总的来说,观察者模式所做的工作就是在解耦,让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响到另一边的变化。