JavaScript设计模式-22.观察者模式
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>