1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
| //用jquery来实现观察者模式
(function($) {
var o = $({});//创建一个jquery空对象
$.extend({//扩展两个jquery静态方法
dingyue:function() {//订阅方法
o.on.apply(o,arguments);
},
fabu:function() {//发布方法
o.trigger.apply(o,arguments);
},
tuiding:function() {//退订方法
o.off.apply(o, arguments);
}
});
//订阅者A
$.dingyue('tianqi',function(e,data){//订阅了天气
console.log('我是订阅者A【收到】'+data);
});
//订阅者B
$.dingyue('zazhi',function(e,data){//订阅了杂志
console.log('我是订阅者B【收到】'+data);
});
//发布者
$.fabu('tianqi', "今天夜间有雷阵雨");//发布者天气发布消息
$.fabu('zazhi', "杂志最近有新版本更新");//发布者杂志发布消息
$.tuiding('zazhi');
//第二次发布消息
$.fabu('tianqi', "天气第二次发布");//发布者天气发布消息
$.fabu('zazhi', "杂志第二次发布");//发布者杂志发布消息,此时发布的消息,订阅者B无法收到了,它退订了
})(jQuery);
//js原声代码实现
//创建发布者构造函数
function Publisher() {
this.subscribers = [];//这个属性用来保存订阅者的引用
}
//为发布者添加一个发送消息给订阅者的方法
Publisher.prototype.deliver = function(data) {
this.subscribers.forEach(function(fn) {
fn(data);
});
return this;
};
//创建订阅者,订阅方法
Function.prototype.subscribe = function(publisher) {
var that = this;
var alreadyExists = publisher.subscribers.some(function(el) {//判断订阅者在发布者属性subscribers是否存在
return el === that;
});
if(!alreadyExists){//如果不存在
publisher.subscribers.push(this);//把订阅者保存到发布者的属性subscribers中,即把订阅者注册到发布者中
}
return this;
};
// 创建订阅者,退订方法
Function.prototype.unsubscribe = function(publisher) {
var that = this;
publisher.subscribers = publisher.subscribers.filter(function(el) {
return el !== that;
});
return this;
};
//运用
var fbA = new Publisher();
var fbB = new Publisher();
//创建一个订阅者A
var dyA = function(data){
console.log("订阅者A接收到的消息为:"+data);
};
var dyB = function(data) {
console.log("订阅者B接收到的消息为:" + data);
};
var dyC = function(data) {
console.log("订阅者C接收到的消息为:" + data);
};
dyA.subscribe(fbA);//订阅者A订阅了发布者fbA;
dyB.subscribe(fbB);//订阅者B订阅了发布者fbB;
dyC.subscribe(fbA).subscribe(fbB);//订阅者C订阅了发布者fbA和发布者fbB;
//有时候,有些订阅者在监听到某一次性的事件后会在回调阶段立即退订该事件。其做法大致如下:
//创建一个订阅者D
var dyD = function(data) {
console.log("订阅者D接收到的消息为:" + data);
//订阅后,立即退订
dyD.unsubscribe(fbB);
};
dyD.subscribe(fbB);//订阅了发布者B,然后监听完发布者B后立即退订
//发布者发送消息
fbA.deliver("欢迎您订阅了我,我是发布者A");//发布者发送资讯时,这个时候,注册到它这里的所有订阅者,都可以接收到这个信息
fbB.deliver("我这里有最新的javscript消息,我是发布者B").deliver('这是我第二次发布的消息');//第二次发布消息时,订阅者D是收不到消息的。
|