对于密集型前端项目而言,业务的复杂程度会导致代码的耦合非常巨大,如何解耦和更加优雅的实现成为每个前端开发工程师的一个追求的目标。前端MVC,观察者模式,面向接口编程等等方案的提出都为我们解决了一些项目中常常碰到的实际问题。
之前winter大大吐槽过javascript 乱用设计模式的方式,我想观察者模式应用在相对独立的模块之间的解耦不属于此列。加上阿当也在他的微博上说到,会不会使用js的消息通知机制,可以区分js的老手和新手之分。由此可见观察者模式对于一些实际开发者而言还是比较讨好的。
那么具体什么是观察者模式,用通俗易懂的话说,就是模块之间的订阅以及广播。假设有A、B两个模块,相互不知道对方的存在(相互独立),B模块订阅了A模块的通知,这个假如时候A 由于状态的改变会发出广播,那么对模块A 订阅了这个状态的B就执行相应的逻辑。 整个订阅和通知的这个机制始终处于第三方,相当于一个接线员的工作,很像一个观察者,就是所谓的观察者模式。在wiki上有更加详细的解释,感兴趣的同学可以看看
观察者模式wiki
这里引用wiki上的对观察者模式的用途阐述:
引用
- 当抽象个体有两个相互依赖的层面时,封装这些层面在单独的物件内可将允许程序设计师单独地去变更重复使用这些物件,而不会产生两者之间的交互的问题。
- 当其中一个物件的变更会影响其他物件,却又不知道多少物件必须被同时变更时。
- 当物件应该有能力通知其他物件,又不应该知道其他物件的实际细节时
上面提到的观察者用途是否似曾相识?工作中的实际项目是否常见呢?我觉得答案是肯定的,除非你的业务逻辑不需要和任何外界的模块交互。举个很简单的例子来说。目前很流行的SNS站点,大多都有发消息的功能,无论是心情也好,微博也好就拿微博举例子吧。在发消息这个动作进行的过程需要做什么事情?
消息发送成功之后通知主页timeline立马显示那条消息,在自己的发的消息数字上+1,甚至在一些SAP(single page app上)还需要更新我发送的消息 timeline 等等。
同样微博的收听,评论等等功能也一样。
比较耦合的写法就是在发送请求成功过后,依次在callback里执行相应的逻辑。这就使得,发消息的模块,必须要知道他发送成功了必须要通知哪几个模块,并且执行他们的逻辑。
而在观察者模式情况下是怎么做的呢?抽象的说,在发送消息的请求成功返回后,发送广播消息已发送成功,所有订阅了这个类型的广播的模块依次自己去执行自己的对应逻辑。这样每个模块只需要面向和自己有关的广播,处理相应的逻辑。而不用关心自己和其他具体模块交互的逻辑。
那么到底如何实现这个观察者模式呢?
其实在我们理解里以后,发现观察者需要提供的最基本的接口有下面三个:
- subscribe 订阅
- fire 发送广播
- unsubscribe 取消订阅
var observer = (function(){
var obList = {};
function subscribe(msgType,callback){
//订阅广播
if(!obList[msgType]){
obList[msgType] = []
}
obList[msgType].push(callback);
}
function fire(msgType, data){
//发送广播
if(obList[msgType]){
for(var i=0,l=obList[msgType].length;i<l;i++){
//发送广播的数据data
obList[msgType][i](data);
}
}
}
function unsubscribe(msgType, callback){
//取消订阅
if(obList[msgType]){
obList[msgType].shift(obList[msgType].indexOf(callback));
}
}
return {
'subscribe' : subscribe,
'fire' : fire,
'unsubscribe' : unsubscribe
};
})()
以上代码是为了阐述观察者模式随手写的单例,不推荐直接使用,我甚至都没有自测,只是把实现的大概思想在这里用代码表述了一遍。当然要注意的是,观察者模式如果管理不善的话,也会导致消息类型的以上的msgType的肆意增长,要优雅的使用观察者模式还需要更好的管理这些msgType,或者可以根据观察的对象不同定义一些不同的频道,这样使得即便观察对象多了也便于维护。
使用观察者模式的好处是你只需要通过这样的设计,就可以避免代码里大量的耦合,做到充分解耦,何乐而不为呢?加上现在DOM LEVEL3 event对象也开始支持以前不支持的但却被很多人实现了的customEvent。通过这个方式也可以实现观察者模式,只不过这个方式依赖DOM和事件对象,或是对于过于抽象的组件也许不适合。其实事件监听器(EventListener)也是观察者模式的一种,现实的例子中观察者模式还是很流行的,所以了解这个模式对前端开发来说很有帮助。
分享到:
相关推荐
一个比较有意思的js库可以为javascript的对象实现观察者模式,以往我们使用javascript实现的观察者模式都是通过使用回调函数配合dom上的event事件来操作的,而“Watch.js”可以为javascript的对象实现观察者模式,...
javascript观察者模式有什么方法_javascript观察者模式有哪些方法.docx
JavaScript观察者模式(经典).docx
javascript观察者模式实现自动刷新效果.docx
本篇文章简单介绍了JavaScript设计模式中的两种,分别是单例模式和观察者模式,并且举了例子便于理解,希望大家一起交流,共同进步。
浅谈javascript面向对象编程,不错的材料
NULL 博文链接:https://shiwuyisheng.iteye.com/blog/799423
浅谈JavaScript编程语言的编码规范
主要是对javascript的面向对象思想的一个理解,有简单的单例模式,工厂模式,观察者模式含代码。
Observer模式也叫观察者模式,是由GoF提出的23种软件设计模式的一种。Observer模式是行为模式之一,它的作用是当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对象状态
浅谈JavaScript对象之教学.pdf
浅谈JavaScript 标准对象_.docx
本文实例讲述了JavaScript设计模式之观察者模式与发布订阅模式。分享给大家供大家参考,具体如下: 学习了一段时间设计模式,当学到观察者模式和发布订阅模式的时候遇到了很大的问题,这两个模式有点类似,有点傻傻...
浅谈JavaScript对象与继承_.docx
浅谈JavaScript for循环 闭包_.docx
我们开始发送消息第三步,在组件三中接收消息 第一步,我们先在main.js中注册一下bus 第二步,我们开始发送消息 第三步,在组件三中接收消息 vue的机制 观察者模式存在的意义 观察者模式 首先,提到观察者...
浅谈Javascript单线程和事件循环.doc
浅谈Javascript数组(推举)_.docx
浅谈javascript在网页制作中的应用.pdf