Javascript設計模式(五)代理模式

YiHzo發表於2018-11-15

使用者無權訪問目標物件,通過代理做授權和控制

代理模式是一種非常有意義的模式。在生活中也能找到代理模式的情景,比如,明星都有經紀人作為代理,如果想請明星來辦一場商業演出,只能聯絡他的經紀人,經紀人會把商業演出的細節和報酬都談好之後,再將合同交給明星籤。

代理實現圖片懶載入

在前端開發中,圖片懶載入是一項非常實用的技術。為了效能優化,我們常常在圖片載入之前用一張圖片佔位,等圖片載入完成之後再將圖片填充到src上,這種場景就很容易實用代理模式。

var myImage = (function() {
	var imgNode = document.createElement('img')
	document.body.appendChild(imgNode)
	return {
		setSrc: function(src) {
			imgNode.src = src
		}
	}
})()

var proxyImage = (function(){
	var img = new Image()
	img.onload = function() {
		myImage.setSrc(img.src)
	}
	return {
		setSrc: function(src) {
			myImage.setSrc('./loading.gif')
			img.src = src
		}
	}
})()

proxyImage.setSrc('https://user-gold-cdn.xitu.io/2016/11/29/805fd2776ae656464329c04f63181266?imageView2/1/w/180/h/180/q/85/format/webp/interlace/1')
複製程式碼

通過proxyImage間接訪問MyImage。proxyImage控制來客戶對MyImage的訪問,並且在此過程中加入一些額外的操作,比如在圖片載入前,先將src設定為本地的loading圖。

快取代理

快取代理可以為一些開銷較大的運算結果暫時的儲存,在下次運算時,如果傳遞的值一致,則可以直接返回前面儲存的結果。

// 建立一個乘積函式
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
複製程式碼

當第二次呼叫proxyMult的時候,本體mult並沒有直接計算,proxyMult直接返回之前的結果

引入代理的意義

為了說明代理的意義,下面引入一個物件導向的設計原則:單一職責原則

  1. 一個類(物件或者函式)而言,應該只能有一個引起它變化的原因。如果一個物件承擔了多項職責,那麼引起變化的原因可能就有多個。
  2. 實際上增加懶載入圖片只是一個景上添花的行為。縱觀整個程式,我們並沒有改變myImage的介面,但是通過代理,給介面新增了新的行為,如果某天不需要了,也不用修改本體。

相關文章