实现
/*
* js 观察者模式 又称 订阅/发布模式
* 通过创建“可观察”对象,当发生一个感兴趣的事件时可将该事件通告给
* 所有观察者,从而形成松耦合
*/
// 通用的发布者
EventPublisher = Base.extend({
publish: function(data, type) {
EventPublisher.publish(data, type);
}
}, {
subscribers : {
any : [] // 事件类型: 订阅者
},
// 将订阅者提供的调用方法添加到subscribers 订阅的事件数组中
subscribe : function(subscriber) {
var type = subscriber.type || 'any';
if (typeof this.subscribers[type] === 'undefined') {
this.subscribers[type] = [];
}
this.subscribers[type].push(subscriber.handleEvent);
},
// 删除订阅者
unsubscribe : function(fn, type) {
this.visitSubscribers('unsubscribe', fn, type);
},
// 循环遍历subscribers中每个元素,并调用他们所提供的方法
publish : function(publication, type) {
this.visitSubscribers('publish', publication, type);
},
// helper
visitSubscribers: function (action, arg, type) {
var pubtype = type || 'any',
subscribers = this.subscribers[pubtype],
i,
max = subscribers.length;
for (i = 0; i < max; i += 1) {
if (action === 'publish') {
// 调用订阅者订阅该事件所提供的方法
subscribers[i](arg);
} else {
// 找到当前订阅事件中提供的方法,并删除
if (subscribers[i] === arg) {
subscribers.splice(i, 1);
}
}
}
}
});
测试
// 实现paper 对象,他所做的就是发布日刊和月刊
Paper = EventPublisher.extend({
daily : function() {
this.publish('今个有重要新闻', 'paper-daily');
},
monthly : function() {
this.publish('每月调查', 'paper-monthly');
},
readWeibo: function(info) {
console.log('重大新闻[' + info + ']');
}
});
// 订阅者对象joe,该对象有2个方法
Person = EventPublisher.extend({
name: null,
constructor: function(config) {
this.name = config.name;
},
drinkCoffee : function(paper) {
console.log(this.name + '开始阅读[' + paper + ']');
},
sundayPreNap : function(monthly) {
console.log(this.name + '开始阅读[' + monthly + ']');
},
weibo: function(msg) {
this.publish(msg, 'person-weibo');
}
});
var paper = new Paper();
var darkness = new Person({
name: 'darkness'
});
EventPublisher.subscribe({
type: 'paper-monthly',
handleEvent: function(data) {
darkness.sundayPreNap(data);
}
});
EventPublisher.subscribe({
type: 'paper-daily',
handleEvent: function(data) {
darkness.drinkCoffee(data);
}
});
EventPublisher.subscribe({
type: 'person-weibo',
handleEvent: function(data) {
paper.readWeibo(data);
}
});
// paper开始发布日刊 和 月刊
paper.daily();
paper.monthly();
// darkness发布微博信息
darkness.weibo('今日头条,2015年啦!');
参考
一个javascript继承的基础类Base.js