JS实现监听模式和观察者模式

[b]引子:[/b]

最近看阮一峰先生的[url=http://www.ruanyifeng.com/blog/2012/12/asynchronous_javascript.html]这篇[/url]文章,文章涉及到观察模式,监听模式相关的设计模式的内容,正好,我最近也用swt做个一个视频批量上传的桌面应用,在这个桌面应用的sdk中,有大量的监听器接口,用来监听该应用的很多组件上的事件,比如按钮的点击事件、树形组件节点的选中事件,等等。我为了实现该应用,也大量应用了监听模式,譬如:文件上传进度的监听,上传列表选中行的事件监听,软件启动时log4j初始化的监听事件,等等。
[img]http://dl.iteye.com/upload/attachment/0078/5511/9bcdefec-7190-39d4-9758-05e99e70ef56.png[/img]
[img]http://dl.iteye.com/upload/attachment/0078/5513/a261a023-e2a1-3627-998c-975567481822.png[/img]
在该应用开发的过程中,我曾经思考过用观察者模式,但最后为了应用代码维护的简单性,所有的事件处理,都统一使用了监听模式。实际上面提到的文件上传进度的监听,上传列表选中行的事件监听,软件启动时log4j初始化的监听事件,只有上传列表选中行的事件监听可以改为观察者模式,原因是因为选中多行时,确实要同时去更新工具栏状态和状态栏显示的信息。

为了对监听模式和观察者模式有一个复习,我回复了阮先生的博客,参考:[url]http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html#comment-267332[/url],回复是通过js实现一个监听模式的例子。实际上,我后来发现这个例子有一些命名上的瑕疵。本想再写一个观察者模式的例子进行回复,无奈阮先生的博客的评论功能实在是太弱了,我监听模式的例子就贴乱了,还烦劳他修改了一次。因此,我才决心写两篇博客交代一下这两个设计模式。当然了,这篇博客我只打算写两个没有什么实际场景的小例子,下篇博客,举例一个真实的场景,用java和js分别给出实现代码。

请看监听模式的代码示例:

[code]
// 事件对象
var Event = function(obj) {
this.obj = obj;
this.getSource = function() {
return this.obj;
}
}

// 监听对象
var F2 = function() {
this.hander = function(event) {
var f1 = event.getSource();
console.log("f2 do something!");
f1.callback();
}
}

// 被监听对象
var F1 = function() {
this.abc = function() {
console.log("f1 do something one!");
// 创建事件对象
var e = new Event(this);
// 发布事件
this.f2.hander(e);
console.log("f1 do something two!");
}

this.on = function(f2) {
this.f2 = f2;
}

this.callback = function() {
console.log("f1 callback invoke!");
}
}

// 主函数
function main() {
var f1 = new F1();
var f2 = new F2();
// 加入监听
f1.on(f2);
f1.abc();
}

// 运行主函数
main();
[/code]

监听模式示例运行结果:
[quote]
f1 do something one!
f2 do something!
f1 callback invoke!
f1 do something two!
[/quote]


观察者模式的代码示例:

[code]
// 观察者对象1
var F2 = function() {
this.update = function(observable, obj) {
console.log("f2 do something!");
for (var i=0, len=obj.length; i<len; i++) {
console.log(obj[i]);
}
observable.callback();
}
}

// 观察者对象2
var F3 = function() {
this.update = function(observable, obj) {
console.log("f3 do something!");
for (var i=0, len=obj.length; i<len; i++) {
console.log(obj[i]);
}
observable.callback();
}
}

// 被观察对象
var F1 = function() {
// 保存所有观察者
var observers = [];

this.abc = function() {
console.log("f1 do something one!");
var datas = ["苹果", "桃子", "香蕉"];
// 通知所有观察者
this.notifyObservers(datas);
console.log("f1 do something two!");
}

this.addObserver = function(observer) {
observers.push(observer)
}

this.callback = function() {
console.log("f1 callback invoke!");
}

this.notifyObservers = function(arg){
if (observers.length == 0) {
return;
};
for (var i = 0, len = observers.length; i < len; i++) {
observers[i].update(this, arg);
}
}
}

// 主函数
function main() {
var f1 = new F1();
var f2 = new F2();
var f3 = new F3();
// 加入观察者
f1.addObserver(f2);
f1.addObserver(f3);
f1.abc();
}

// 运行主函数
main();
[/code]

观察者模式示例运行结果:
[quote]
f1 do something one!
f2 do something!
苹果
桃子
香蕉
f1 callback invoke!
f3 do something!
苹果
桃子
香蕉
f1 callback invoke!
f1 do something two!
[/quote]

总结:
1、在观察者模式示例中,被观察的对象有两个观察者,因此两个观察者的逻辑被各自调用了;在监听模式示例中,被监听的对象只有一个监听者,因此只有一个监听者逻辑被调用了。监听模式示例中的监听者也可以有多个,但通知的时候需要逐一通知,比较麻烦,而观察者就方便多了,所以,当一个对象只有一个需要通知的对象时,使用监听者模式比较简单,而当需要通知的对象比较多时,采用观察者模式比较简单明了,这些要结合相应的业务场景,譬如,邮件列表的订阅就适合用观察者模式。

2、这两种模式都使用了回调的机制,唯一区别不同的是,监听模式使用一个Event对象来保留回调的钩子(事件源处传入的对象,一般是被监听者本身),而观察者模式没有抽象Event事件对象,使用参数的方式将钩子传到观察者,并附带传入了一些其他的信息。因此,观察者模式和监听者模式都是使用回调机制,其设计思想异曲同工。

3、这两种模式都是采用了对象之间组合的方式进行职责解耦,这是软件设计的指导性思想,无论我们是否很精确的实现这两种设计模式,只要在设计中把握尽量采用组合方式,我们的软件结构就会相对比较清晰,耦合度就相对比较低了,这是这两种设计模式给我们的启示!

下篇我们通过实际的例子,使用Js和Java复习一下这两种设计模式!

[color=gray]如果您觉得本文对您有益,请点击博文后的google广告,对作者表示支持,谢谢![/color]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值