最近在读《javascript设计模式与开发实践》,在这里把文中的各种设计模式写出来,以便加深记忆,也可以分享给初学者。如果你不了解设计模式,那么强烈推荐你阅读一下这本书,相信它可以颠覆你的编程思维,助你打通任督二脉。
假设有对象A和对象B,代理模式相当于对象C,对对象A进行封装,对象B只需要与对象C进行交流。对象C就是一个替身。简而言之就是用一个对象代表另外一个对象,对应现实生活中的场景就是明星王宝强和经纪人宋喆之间的关系。经纪人可以全权代表明星和客户谈判,最后把谈判结果给明星,明星决定签约与否。
代理模式可以用在图片延迟加载,延迟加载的原理是:先用loading图片替代图片的真实src,创建一个img元素(代理)加载图片的真实src。加载完之后,图片的src替换掉loading。下面就看看代码怎么实现:
myImage = (function(){ var img = document.createElement("img"); document.body.appendChild(img); return { setSrc:function(src){ img.src = src; } }})()proxyImage = (function(){ var img = new Image; img.onload = function(){ myImage .setSrc(this.src) } return { setSrc:function(src){ myImage.setSrc("load.gif"); img.src = src; } }})()proxyImage.setSrc('http://test.jpg');
代理的意义
也许你会觉得一个小小的延迟加载何必要用到设计模式?不用代理模式的确也可以做到。那么引入代理模式有什么好处呢?下面我们抛开代理模式,用常用的方式实现图片延迟加载:
myImage = (function(){ var img = document.createElement("img"); document.body.appendChild(img); var imgNode = new Image; imgNode.onload = function(){ img.setSrc(this.src) } return { setSrc:function(src){ img.setSrc("load.gif"); imgNode.src = src; } }})()myImage.setSrc('http://test.jpg');
上面的myImage除了负责加载图片以外,还负责延迟加载。将来网速越来越快,如果有一天不需要延迟加载,那么就需要修改myImage函数。这也违反了面向对象设计原则中的——单一职责原则。单一职责原则要求对象只有一个职责(功能),引起对象变化的原因也只能有一个,如果对象有多个职责,那么这个对象会变得非常大,引起对象变化的原因有多个。单一职责也是为了程序低耦合高内聚。
反观代理模式,myImage只负责加载图片,proxyImage只负责延迟加载,如果以后不需要延迟加载只需要修改调用方式即可。