经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
代理模式
来源:cnblogs  作者:人生之外的路途  时间:2021/2/18 15:34:57  对本文有异议

代理模式

场景:小明送花记

小明喜欢一群漂亮的女神MM*,所以开始了疯狂的送花行为,开始他自己去送花,发现被别人发现了会影响后面的追求其他女神,所以小明踏上了找代理送花的这条不归路

初识代理

  • 小明追MM送花,直接送
  • 小明选择MM的好朋友(小明同桌)送花
  1. let Flower = function(flowerName) {
  2. this.flowerName = flowerName
  3. }
  4. let XiaoMing = {
  5. sendFlower : function (target){
  6. let flower = new Flower("牡丹");
  7. target.receiveFlower(flower);
  8. }
  9. }
  10. const MM = {
  11. receiveFlower : function (flower){
  12. console.log("MM收到一束花: " + flower.flowerName)
  13. }
  14. }
  15. const Frient = {
  16. receiveFlower : function(flower){
  17. MM.receiveFlower(flower);
  18. }
  19. }
  20. XiaoMing.sendFlower(MM)
  21. XiaoMing.sendFlower(Frient)

你会发现结果是一样的,所以这个代理有什么用呢???效果都一样嘛!!!会要转手,多麻烦!!!

别着急,继续看下去就知道了

初见代理作用

  • 小明上次失败了,他觉得是可能是MM心情不好,所以拒绝了他
  • 吸取上次的教训,这次花了多一点钱,找了一个靠谱的代理,朋友2,希望她能在MM2心情好的时候送出花花
  1. let MM2 = {
  2. receiveFlower : function(flower){
  3. console.log("MM2收到一束:" + flower.flowerName)
  4. },
  5. listenGood: function(fn){
  6. // 假设1秒后心情变得特别好
  7. setTimeout(() => {
  8. fn();
  9. }, 1000);
  10. }
  11. }
  12. let Frient2 = {
  13. receiveFlower:function(flower){
  14. MM2.listenGood(() => {
  15. MM2.receiveFlower(flower);
  16. });
  17. }
  18. }
  19. XiaoMing.sendFlower(Frient2)

这里可以看出,代理的作用还是很大的,能决定事件触发执行时间(这里更好的是时机)

代理 - 保护模式

  • 小明表白失败了,他觉得是自己买错花了,表白怎么能用牡丹呢?于是买了一束玫瑰准备继续表白
  • 找到了第三个MM3,但是这个MM3的朋友知道小明前面的事迹
  • MM3的朋友觉得小明太渣了,直接拒绝了帮忙送花的事
  1. XiaoMing = {
  2. sendFlower : function (target){
  3. let flower = new Flower("玫瑰");
  4. target.receiveFlower("小明", flower);
  5. }
  6. }
  7. let MM3 = {
  8. receiveFlower : function(flower){
  9. console.log("MM3收到一束:" + flower.flowerName)
  10. }
  11. }
  12. let Friend3 = {
  13. receiveFlower: function(name , flower){
  14. if(name === "小明"){
  15. console.log(name + ",你不配给我替你送花")
  16. return;
  17. }
  18. MM3.receiveFlower(flower);
  19. }
  20. }
  21. XiaoMing.sendFlower(Friend3);

这里可以看到我们可以在外设置关卡,如果说是渣渣,我们不让进入后面部分,这样可以很好的保护内部

  • 小明受不了,“你不帮忙送,怎么不早说”,这接连的失败,然后就委屈巴巴的哭了,嘴里还念叨着:“这是我一个星期的生活费呀!!!”
  • 朋友3:“你以前都没有问我呀,我咋知道呢!!!”
  • 小明:“哦,原来还是我的错!!!”
  • 朋友3看着小明的样子:“看你这样子,只要你耐心改过,不这么花心,我可以考虑帮你一回”
  • 小明答应了,于是又改变了,小明会提前问朋友3是否愿意送花,在决定买花
  1. XiaoMing = {
  2. sendFlower : function (target){
  3. target.receiveFlower("小明", function(){
  4. return new Flower("玫瑰");
  5. });
  6. }
  7. }
  8. MM3 = {
  9. receiveFlower : function(flower){
  10. console.log("MM3收到一束:" + flower.flowerName)
  11. }
  12. }
  13. Friend3 = {
  14. receiveFlower: function(name , fn){
  15. if(name === "小明"){
  16. console.log(name + ",你还不配给我替你送花")
  17. return;
  18. }
  19. // 有送花的资格了
  20. let flower = fn();
  21. MM3.receiveFlower(flower);
  22. }
  23. }
  24. XiaoMing.sendFlower(Friend3);

上面不难看出,其实我们可以把一些很消耗资源的事情放在我们通过代理后再做,这样就节省了很多不必要的消耗

代理模式 - 虚拟代理

不使用代理的图片预加载

  1. var myImageNoProxy = (function(){
  2. var imgNode = document.createElement("img");
  3. document.body.appendChild(imgNode);
  4. var img = new Image;
  5. img.onload = function(){
  6. // 模拟加载过程
  7. setTimeout(() => {
  8. imgNode.src = img.src;
  9. }, 1000);
  10. }
  11. return {
  12. setSrc: function(src){
  13. imgNode.src = "../../work/图片/loadding.jpg";
  14. img.src = src;
  15. }
  16. }
  17. }())
  18. myImageNoProxy.setSrc("../../work/图片/test.png")

使用代理的图片预加载

  1. let myImage = (function(){
  2. let imgNode = document.createElement("img");
  3. document.body.appendChild(imgNode);
  4. return {
  5. setSrc:function(src) {
  6. imgNode.src = src;
  7. }
  8. }
  9. }())
  10. myImage.setSrc("../../work/图片/test.png")
  11. let proxyMyImage = (function(){
  12. let img = new Image();
  13. img.onload = function(){
  14. // 模拟加载过程
  15. setTimeout(() => {
  16. myImage.setSrc(img.src)
  17. }, 1000);
  18. }
  19. return {
  20. setSrc:function(src){
  21. myImage.setSrc("../../work/图片/loadding.jpg")
  22. img.src = src;
  23. }
  24. }
  25. }())
  26. proxyMyImage.setSrc("../../work/图片/test.png")

整体来看,其实两个图片的预加载都差不多,但是代理模式相对会好一点,每个方法都有自己的作用,后面有部分图片不需要预加载的时候只需要更换方法,而无需改变方法内部代码

请求统一上传

场景

点击一下复选框就会上传服务器,但是这样比较消耗性能,所以更改为点击的时候先保存在本地,等到不再操作的时候就一起上传上去

  1. let sendToServer = function(id){
  2. console.log("开始上传到服务器... id :" + id);
  3. }
  4. var proxySendToServer = (function(){
  5. var cache = [], // 缓存一段时间内的id列表
  6. timer = null; // 定时器
  7. return function(id){
  8. // 缓存id
  9. cache.push(id);
  10. // 如果上一个timer还在,那么就结束
  11. if(timer){
  12. return;
  13. }
  14. // 否则设置定时器
  15. timer = setTimeout(() => {
  16. // 真正的上传到服务器
  17. sendToServer(cache.join(","));
  18. clearTimeout(timer)
  19. timer = null;
  20. cache = [];
  21. }, 2000);
  22. }
  23. }())
  24. let checkBoxs = document.getElementsByTagName("input");
  25. for (let index = 0; index < checkBoxs.length; index++) {
  26. const element = checkBoxs[index];
  27. element.onclick = function(){
  28. // 使用代理上传到服务器
  29. if(this.checked === true){
  30. proxySendToServer(this.id);
  31. }
  32. }
  33. }

代理总结

代理和本体接口的一致性:通过上面的代码可以看到,我们代理和本体都是暴露了相同的接口,代理接手请求的过程对于用户来说是透明的,用户并不清楚代理和本体的区别

  • 用户可以放心请求代理,他只关心是否得到自己想要的结果

  • 在任何使用本体的地方都可以直接使用代理替代,反之亦然

代理意义:面向对象中有一个设计原则 ----> 单一职责原则【就是一个类(通常也包括一个对象和函数等)而言,应该仅有一个引起它变化的原因,如果一个对象承担了多项职责,就意味着这个对象将变得巨大,引起它变化的原因可能有很多个。面向对象设计鼓励将行为分布到细粒度的对象中,如果一个对象承担太多职责,等于把这些职责耦合到一起,这种耦合会导致脆弱和低内聚的设计】

原文链接:http://www.cnblogs.com/wangzhaoyv/p/14378748.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号