代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问。
在Web开发中,图片预加载是一种常用的技术,如果直接给某个img标签节点设置src属性,由于图片过大或者网络不佳,图片的位置往往有段时间会是一片空白。常见做法是先用一张loading图片占位,然后用异步的方式加载图片,等图片加载好了再把它填充到img节点里,这种场景就适合使用虚拟代理。
创建一个普通本体对象,负责往页面中创建一个img标签并对外提供一个setSrc接口:
var myImage = (function() {
var imgNode = document.createElement('img')
document.body.appendChild(imgNode)
return function(src) {
imgNode.src = src
}
})()
此时可以直接使用这个对象去创建img标签并设置src展示图片:
myImage('./test/picture.png') // 正式需要加载的图片
为了达到预加载效果,我们引入代理对象:
var proxyImage = (function() {
var img = new Image
img.onload = function() {
myImage(this.src)
}
return function(src) {
myImage('./test/loading.gif') // 过度gif
img.src = src
}
})()
将图片地址传给代理对象来实现懒加载效果:
proxyImage('./test/picture.png') // 正式需要加载的图片
代理方法一边加载真实地址的图片,一边先调用myImage展示loading动画。等实际图片onload完毕再次调用myImage展示实际图片,全过程myImage会被调用两次。
其实一个懒加载,一个方法就可以搞定,但是在这里拆成了代理模式来做的意义是为了符合——单一职责原则。指的是,就一个类(通常也包括对象和函数等)而言,应该仅有一个引起它变化的原因。如果一个对象承担了多项职责,就意味着对象变得巨大,等于多个职责耦合到一起,这种耦合会导致脆弱和低内聚的设计。