代理模式
代理英文是proxy,就像经纪人一样,如果有通告需要找到明星,不能直接和明星直接接触,而是要找经纪人,经纪人进行筛选后,然后在和明星进行沟通。经纪人的所作就是代理类的作用
比如小明想送花给小红
下面的代码没有进行任何代理,而是小明直接送给了小红
1 <script> 2 function Flower(name) { 3 this.name = name 4 } 5 var xiaoming = (function() { 6 var flower = new Flower('玫瑰花'); 7 return { 8 name: '小明', 9 sendFlower: function(target) { 10 // 送的目标 11 target.getFlower(flower, this) 12 } 13 } 14 })() 15 var xiaohong = { 16 getFlower: function(flower, person) { 17 console.log("小红收到了" + person.name + '的' + flower.name) 18 } 19 } 20 xiaoming.sendFlower(xiaohong) 21 </script>
突然有一天,小红和小明生气了,小明为了哄小红开心,想送小红礼物,但是此时小红由于还在生小明的气,所以不会搭理小明。此时小明想到了小红的闺蜜,让她做代理,然后把礼物送给小红的闺蜜,让闺蜜适时送给小红
1 <script> 2 function Flower(name) { 3 this.name = name 4 } 5 var xiaoming = (function() { 6 var flower = new Flower('玫瑰花'); 7 return { 8 name: '小明', 9 sendFlower: function(target) { 10 // 送的目标 11 target.getFlower(flower, this) 12 } 13 } 14 })(); 15 16 var guimi = (function() { 17 return { 18 name: "闺蜜", 19 flower: null, 20 sendPerson: null, 21 // 获取小红心情的状态 22 getState: function(state) { 23 // 如果此时小红的心情比较好,送花 24 if (this.flower && state == "心情很好") { 25 xiaohong.getFlower(this.flower, this.sendPerson) 26 } 27 }, 28 getFlower: function(flower, person) { 29 // 得到小明的信息和礼物 30 this.flower = flower.name; 31 this.sendPerson = person.name; 32 console.log("闺蜜收到了" + person.name + '的' + flower.name) 33 } 34 } 35 })(); 36 37 var xiaohong = (function() { 38 var state; 39 var timer = setInterval(function() { 40 if (Math.random() > 0.5) { 41 state = '心情很好' 42 } else { 43 state = '心情不好' 44 } 45 guimi.getState(state) 46 }, 1000) 47 return { 48 getFlower: function(flower, person) { 49 // 接收自闺蜜转接的礼物 50 console.log("小红收到了来自闺蜜转接自" + person + "的" + flower) 51 } 52 } 53 })() 54 xiaoming.sendFlower(guimi) 55 </script>
上面的代码中guimi处于一个代理状态,代理的是对小红的事件过程
缓存代理
我们可以使用代理模式进行缓存处理,也叫做缓存代理
缓存代理就是记录已经进行的进行(结果),然后再次执行的时候和代理类进行比对,然后判断是抛出已有的,还是执行新的功能
比如我们下面是计算数字的阶乘,已有的计算,我们直接抛出缓存,没有的执行阶乘函数
1 <script> 2 function factorial(number) { 3 console.log("对" + number + "的阶乘计算"); 4 for (var i = number, result = 1; i >= 1; i--) { 5 result *= i; 6 } 7 return result; 8 } 9 console.log(factorial(5)) 10 </script>
此时我们多输出几个结果会发现
每次都会进行调用函数
1 <script> 2 function factorial(number) { 3 console.log("对" + number + "的阶乘计算"); 4 for (var i = number, result = 1; i >= 1; i--) { 5 result *= i; 6 } 7 return result; 8 } 9 // 设置一个代理类,缓存已经计算过的信息 10 var factorialProxy = (function() { 11 var note = {}; 12 return function(number) { 13 // 对已有内容的判断 14 return note[number] ? note[number] : note[number] = factorial(number) 15 } 16 })() 17 console.log(factorialProxy(5)) 18 console.log(factorialProxy(5)) 19 console.log(factorialProxy(5)) 20 console.log(factorialProxy(6)) 21 </script>
此时我们设置一个代理类会发现,已经进行过的不在输出
代理类实现图片loading
我们可以通过代理类来实现图片的loading状态显示
1 <script> 2 function MyImage(src) { 3 // 创建节点 4 this.oImg = document.createElement("img"); 5 // 节点上树 6 document.body.appendChild(this.oImg); 7 } 8 MyImage.prototype.setSrc = function(src) { 9 this.oImg.src = src; 10 }; 11 // 代理类 12 function MyImageProxy(src) { 13 this.myImage = new MyImage(); 14 // 给图片设置初始的loading状态,防止如果图片不能预期加载,或者图片加载缓慢的时候的替换状态 15 this.myImage.setSrc("images/loading.gif"); 16 // image就是一个 钩子,作用是用来表示当图片加载完毕之后,让MyIamge的实例进行渲染 17 var image = new Image(); 18 image.src = src; 19 var self = this; 20 // onload表示当图片加载完毕之后,此时的图片是整张图的状态,而不是部分渲染 21 image.onload = function() { 22 self.myImage.setSrc(src) 23 } 24 } 25 new MyImageProxy("images/0.jpg") 26 new MyImageProxy("images/1.jpg") 27 new MyImageProxy("images/2.jpg") 28 </script>
此时我们降低网速可以看到loading效果