1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="UTF-8">
5 <title>javascript高级语法22-观察者模式</title>
6 </head>
7 <body onload="init()">
8 <div id="box"></div>
9 <script>
10 //扩展函数 forEach和filter
11
12 Function.prototype.method = function(name, fn) {
13 this.prototype[name] = fn;
14 return this;
15 };
16 if (!Array.prototype.forEach) {
17 Array.method('forEach', function(fn, thisObj) {
18 var scope = thisObj || window;
19 for ( var i = 0;len < this.length; ++i ) {
20 //这样写不是简单的函数调用,是在函数调用的同事把this重新定位
21 fn.call(scope, this[i], i, this);
22 }
23 });
24 }
25 //Array过滤器
26 if (!Array.prototype.filter ) {
27 Array.method('filter', function(fn, thisObj) {
28 var scope = thisObj || window;
29 var a = [];
30 for ( var i = 0;len < this.length; ++i ) {
31 //看看过滤函数,真留下来,假的删除
32 if ( !fn.call(scope, this[i], i, this) ) {
33 continue;
34 }
35 a.push(this[i]);
36 }
37 //返回新的数组
38 return a;
39 });
40 }
41
42 /*观察者模式:
43 * 分为两个角色:观察者和被观察者
44 * 观察者模式的目的在于对程序的内在变化进行观察,当其有变化的时候可以得知,并作出相应反应
45 */
46
47 /*模拟订阅者和报社之间的关系
48 *实际操作分为(推模式,拿模式)
49 * 推送->长链接技术
50 * 拿模式->定时去后台取得
51 */
52
53 function BusinessOne(name){
54 this.name = name;
55 //订阅者集合
56 this.subscribers = new Array();
57 }
58 //订阅者的发送消息的方法(推模式)
59 BusinessOne.prototype.delive = function(news){
60 var self = this;
61 //给每一个订阅者发送消息
62 this.subscribers.forEach(function(fn){
63 //调用接收者处理信息的函数
64 fn(news,self);
65 })
66 }
67 //扩展公共订阅的函数和取消订阅的函数
68 Function.prototype.subscribe = function(publisher){
69 var that = this;
70 //some访问数组对象,并且以参数的形式传回回调函数
71 //至少有一次返回是true的 那么some就是真
72 var alreadyExist = publisher.subscribers.some(
73 function(el){
74 //处理不能重复订阅的功能
75 if(el == that){
76 return;
77 }
78 }
79 );
80 //没有订阅就可以订阅
81 if(!alreadyExist){
82 publisher.subscribers.push(that);
83 }
84 return this;
85 }
86 //取消
87 Function.prototype.unsubscribe = function(publisher){
88 var that = this;
89 publisher.subscribers = publisher.subscribers.filter(
90 function(el){
91 if(el !== that){
92 return el;
93 }
94 }
95 );
96 return this;
97 }
98
99 //创建发布者的实例
100 var b1 = new BusinessOne("CCTV");
101 var b2 = new BusinessOne("中国国防部");
102
103 //发布(门面模式)
104 function addEventFacada(el,type,fn){
105 if(window.addEventListener){
106 //firefox
107 el.addEventListener(type,fn,false);
108 }else if(window.attachEvent){
109 //IE
110 el.attachEvent("on"+type,fn);
111 }else{
112 el["on"+type] = fn;
113 }
114 }
115 //主应用函数
116 var init = function(){
117 //创建观察者
118 var pageOne = function(news){
119 document.getElementById("info").value =
120 "我发现了: "+"["+arguments[1].name +"] 发来的信息 --->"+news;
121 }
122 //订阅
123 pageOne.subscribe(b1).subscribe(b2);
124 //增加绑定事件
125 addEventFacada(document.getElementById("cctv"),"click",function(){
126 b1.delive(document.getElementById("cctvText").value);
127 });
128 addEventFacada(document.getElementById("gfb"),"click",function(){
129 b2.delive(document.getElementById("gfbText").value);
130 });
131 }
132 </script>
133
134 <input type="text" id="cctvText"/>
135 <input type="button" value='cctv发送' id="cctv"/>
136 <br />
137 <input type="text" id="gfbText"/>
138 <input type="button" value='国防部发送' id="gfb"/>
139 <br />
140 <textarea id="info" cols="60" rows="20"></textarea>
141
142 </body>
143 </html>