代理模式
代理模式顧名思義,就是通過一個代理去處理問題,例如黑道頭子去買軍火,一般都是讓自己的頭號手下去買,自己不參與實際交易~~
虛擬代理
我們先從常見的圖片佔位圖片代理來說明。
通常情況下,我們加載圖片的姿勢是這樣的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<!-- https://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-747189.jpg -->
<!-- https://www.baidu.com/img/xinshouye_4d9e7ecaa1b5f78475bf13965c6142d1.png -->
<img id="image" src="" alt="">
<script>
var mgImage = (function(){
var img = document.getElementById('image');
// 因爲我們需要一個方法 去供代理使用,所以這裏返回的是對象。
return {
setImage: function(src){
img.src = src;
}
}
})();
mgImage.setImage('https://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-747189.jpg');
</script>
</body>
</html>
沒錯,打開非常卡,因爲我用的是一個外國網站的圖片。
使用代理佔位圖片來加載就是一個非常好的方法。如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<!-- https://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-747189.jpg -->
<!-- https://www.baidu.com/img/xinshouye_4d9e7ecaa1b5f78475bf13965c6142d1.png -->
<img id="image" src="" alt="">
<script>
var mgImage = (function(){
var img = document.getElementById('image');
return {
setImage: function(src){
// 2.設置成功,顯示佔位圖片。
img.src = src;
}
}
})();
var poxyImge = (function(){
// 怎樣判斷我們需要的圖片加載完成,首先創建一個圖片實例poxyImg,用onload判斷。
var poxyImg= new Image();
poxyImg.onload = function(){
// 4.當真實圖片地址加載完畢,添加到body的img標籤裏,完成代理。
mgImage.setImage(this.src)
}
return {
setImage: function(src) {
// 1.先給img加載佔位圖片。
mgImage.setImage('https://www.baidu.com/img/xinshouye_4d9e7ecaa1b5f78475bf13965c6142d1.png');
// 3.給poxyImg實例添加真實圖片地址
poxyImg.src =src;
}
}
})()
poxyImge.setImage('https://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-747189.jpg');
</script>
</body>
</html>
當然我們也可以放在一個函數當中,這樣就違反了單一原則和開放封閉原則,上面的代理模式,如果我們以後不需要這個圖片佔位,直接用mgImage函數調用方法就可以了。
如果不用代理模式如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<!-- https://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-747189.jpg -->
<!-- https://www.baidu.com/img/xinshouye_4d9e7ecaa1b5f78475bf13965c6142d1.png -->
<img id="image" src="" alt="">
<script>
var mgImage= (function(){
var img = document.getElementById('image');
var poxyImg = new Image;
poxyImg.onload = function(){
img.src = this.src
}
return {
setImage: function(src){
img.src = 'https://www.baidu.com/img/xinshouye_4d9e7ecaa1b5f78475bf13965c6142d1.png';
poxyImg.src = src;
}
}
})();
mgImage.setImage('https://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-747189.jpg')
</script>
</body>
</html>
這樣也能完成,但是對於以後的維護成本將會提升很多,因爲要去mgImage函數中去修改原有的代碼,是非常不划算的,而且容易產生BUG。
緩存代理
常常用於比較大的計算開銷,如果傳入的參數一致,則直接返回結果,無需計算。
比方說如下栗子,
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script>
var mult = function () {
console.log('start');
var a = 1;
for (var i = 0; i < arguments.length; i++) {
a = a*arguments[i];
}
return a;
}
var poxyMult = (function () {
var cache = {};
return function () {
// 定義對象KEY
var args = Array.prototype.join.call(arguments, ',');
// 判斷KEY是否存在,不存在,新建一個key value
if (!cache[args]) {
cache[args] = mult.apply(this, arguments)
}
// 返回當前key 對應的value
return cache[args];
}
})()
var num = poxyMult(1,2,4,9); // 72
var num1 = poxyMult(1,2,4,9); //72
</script>
</body>
</html>
上面就使用了緩存代理,如果傳入參數一樣的情況下,會直接返回cache裏面的值,當然這樣寫的話,我們只能計算乘積,其實我們可以進行解耦,在原先的poxyMult中,我們不僅進行了緩存,還把mult函數直接綁定在裏面,這樣是不好的,我們改寫下。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script>
var mult = function () {
console.log('start');
var a = 1;
for (var i = 0; i < arguments.length; i++) {
a = a*arguments[i];
}
return a;
}
var createProxyFactory = function (fn) {
var cache = {};
return function () {
var args = Array.prototype.join.call(arguments, ',');
if (!cache[args]) {
cache[args] = fn.apply(this, arguments)
}
return cache[args];
}
}
var add = function () {
console.log('start');
var a = 1;
for (var i = 0; i < arguments.length; i++) {
a = a + arguments[i];
}
return a;
}
var poxyMult = createProxyFactory(mult)
var poxyAdd = createProxyFactory(add)
var num = poxyMult(1,2,4,9); // 72
var num1 = poxyAdd(1,2,4,9); // 17
</script>
</body>
</html>
改寫後的函數,我們新增一個ADD的計算函數,直接將函數傳入createProxyFactory函數中,就實現了加法的緩存,這樣我們就能實現多種計算的緩存。
這也是實現面向對象的開放封閉原則。