代理模式是為一個對象提供一個代用品或占位符,以便控制對它的訪問。
例子一 圖片預加載
var myImage = (function(){
var imgNode = document.createElement('img');
imgNode.className = '123';
document.body.appendChild(imgNode);
return {
setSrc : function(src){
imgNode.src = src;
}
}
})();
var proxyImage = (function(){
var img = document.createElement('img');
img.onload = function(){
console.log(this);//這里的this,指向的是上面創建的img,不是imgNode
myImage.setSrc(this.src);
}
return {
setSrc : function(src){
myImage.setSrc('http://o8kanx15h.bkt.clouddn.com/0.jpg');
img.src = src;
}
}
})();
proxyImage.setSrc('http://o8kanx15h.bkt.clouddn.com/octoliberty.png');
下面是不使用代理模式
var myImage = (function(){
var imgNode = document.createElement('img');
imgNode.className = '123';
document.body.appendChild(imgNode);
var img = new Image;
img.onload = function(){
imgNode.src = img.src;
}
return {
setSrc : function(src){
imgNode.src = 'http://o8kanx15h.bkt.clouddn.com/0.jpg';
img.src = src;
}
}
})();
myImage.setSrc('http://o8kanx15h.bkt.clouddn.com/octoliberty.png');
那么為什么要使用代理模式呢,這么小的功能貌似不用模式也能實現,原因有下面幾點
- 單一職責原則:就一個類來說,應該僅有一個引起它變化的原因。如果一個對象承擔了多項責任,就意味著對象將變得巨大,引起它變化的原因可能會有多個。如果一個對象承擔的職責過多,等于把這些職責耦合到了一起,這種耦合會導致脆弱和低內聚的設計。
- 可能會違反開放-封閉原則。如果我們需要加載的圖片很小,或許以后網速快到不用預加載了,我們可能希望刪掉預加載的功能,這個時候,我們就不得不去更改myImage里面的代碼了。
實際上,我們需要的只是給img節點設置src,預加載只是一個錦上添花的功能。這里把預加載功能放到另一個對象里(代理)。這個時候,代理負責預加載,預加載成功后,把請求重新交給本體myImage
例子二 計算乘積
var mult = function(){
console.log('開始');
var a = 1;
for(var i = 0,l = arguments.length;i < l; i++){
a = a * arguments[i];
}
return a;
};
var proxyMult = (function(){
var cache = {};
return function(){
var args = Array.prototype.join.call(arguments,',');
if(args in cache){
return cache[args];
}
return cache[args] = mult.apply(this,arguments);
}
})();
proxyMult(1,2,3,4);//開始 24
proxyMult(1,2,3,4);//24