js中的观察者模式

//如下实现一个通用发布者
//定义发布者对象...{}是定义一个对象
var publisher = {
subscribers: {
any: [] //事件类型:订阅者 event type: subscribers
},
subscribe: function(fn,type){
type = type || 'any';
if(typeof this.subscribers[type] === "undefined"){
this.subscribers[type] = [];
}
this.subscribers[type].push(fn);
},
unsubscribe: function(fn,type){
this.visitSubscribers('unsubscribe', fn, type);
},
publish: function(publication, type){
this.visitSubscribers('publish',publication,type);
},
visitSubscribers: function(action,arg,type){
var pubtype = type ||'any', //发布的类型
subscribers = this.subscribers[pubtype], //这个类型的接受者数组
i,
max = subscribers.length;

for(i=0;i<max;i++){
if(action === "publish"){ //发布
subscribers[i](arg);
} else { //取消订阅
if(subscribers[i] === arg){
subscribers.splice(i,1);
}
}
}
}
};
//定义一个函数makePublisher(),它接受一个对象作为对象,通过把上述通用发布者的方法复制到该对象中,从而将其转换为一个发布者
function makePublisher(o){
var i;
for(i in publisher) {
if(publisher.hasOwnProperty(i) && typeof publisher[i] === "function"){
o[i] = publisher[i];
}
}
o.subscribers = {any: []};
}
//实现paper对象
var paper = {
daily: function(){
this.publish("big news today");
},
monthly: function(){
this.publish("interesting analysis","monthly");
}
};
//将paper构造成一个发布者
makePublisher(paper); //makePublisher方法把发布者publisher的方法复制到paper对象中,从而使其成为一个发布者
//以上已经有了一个发布者。看看订阅对象joe,该对象有两个方法:注册时,将此方法传入paper的订阅方法,完成注册,则在发布消息时会调用该方法
var joe = {
drinkCoffee: function(paper) {
console.log('Just read' + paper);
},
sundayPreNap : function(monthly){
console.log('About to fall asleep reading this ' + monthly);
}
};


//paper注册joe(即joe向paper订阅)
paper.subscribe(joe.drinkCoffee); //订阅any类型
paper.subscribe(joe.sundayPreNap,'monthly'); //定义monthly类型
//即joe为默认“any”事件提供了一个可被调用的方法,而另一个可被调用的方法则用于当“monthly”类型的事件发生时的情况。现在让我们来触发一些事件:
paper.daily(); //Just readbig news today
paper.monthly(); //About to fall asleep reading thisinteresting analysis
var Jack = {
readPaper: function(paper){
console.log('Jack read' + paper);
}
};
paper.subscribe(Jack.readPaper);
paper.daily(); //输出: Just readbig news today Jack readbig news today

//以上代码的好处在于,paper对象并没有硬编码joe,而joe中也并没有硬编码paper。此外,代码中也没有那些知道一切的中介者对象。由于参与对象是松耦合的,我们可以向paper添加更多的订阅者而根本不需要修改这些对象。

//进一步扩展,让joe成为发布者(比如:博客和微博上任何人都可以是发布者)
makePublisher(joe);
joe.tweet = function(msg) {
this.publish(msg);
};
//现在,paper的公关部门决定读取读者的tweet,并订阅joe的信息,那么需要提供方法readTweets():
paper.readTweets = function(tweet){
console.log('Call big meeting! Someone ' + tweet);
};
joe.subscribe(paper.readTweets); //paper订阅joe的tweet
joe.tweet('hello the world!'); //Call big meeting! Someone hello the world!


另一种思路

var Event = {
// 通过on接口监听事件eventName
// 如果事件eventName被触发,则执行callback回调函数
on: function (eventName, callback) {
//我的代码
if(!this.handles){
this.handles={};
}
if(!this.handles[eventName]){
this.handles[eventName]=[];
}
this.handles[eventName].push(callback);
},
// 触发事件 eventName
emit: function (eventName) {
//你的代码
if(this.handles[arguments[0]]){
for(var i=0;i<this.handles[arguments[0]].length;i++){
this.handles[arguments[0]][i](arguments[1]);
}
}
}
};
// 测试1
Event.on('test', function (result) {
console.log(result);
});
Event.on('test', function () {
console.log('test');
});
Event.emit('test', 'hello world'); // 输出 'hello world' 和 'test'
var person1 = {};
var person2 = {};
Object.assign(person1, Event);
Object.assign(person2, Event);
person1.on('call1', function () {
console.log('person1');
});
person2.on('call2', function () {
console.log('person2');
});
person1.emit('call1'); // 输出 'person1'
person1.emit('call2'); // 没有输出
person2.emit('call1'); // 没有输出
person2.emit('call2'); // 输出 'person2'

猜你喜欢

转载自blog.csdn.net/lvruiyang_1993/article/details/80267818