摘要:文章系列設(shè)計(jì)模式單例模式設(shè)計(jì)模式策略模式設(shè)計(jì)模式代理模式概念代理模式是為一個(gè)對(duì)象提供一個(gè)代用品或占位符,以便控制對(duì)它的訪問(wèn)。
前言
本系列文章主要根據(jù)《JavaScript設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐》整理而來(lái),其中會(huì)加入了一些自己的思考。希望對(duì)大家有所幫助。
文章系列js設(shè)計(jì)模式--單例模式
js設(shè)計(jì)模式--策略模式
js設(shè)計(jì)模式--代理模式
概念代理模式是為一個(gè)對(duì)象提供一個(gè)代用品或占位符,以便控制對(duì)它的訪問(wèn)。
UML類(lèi)圖 場(chǎng)景比如,明星都有經(jīng)紀(jì)人作為代理。如果想請(qǐng)明星來(lái)辦一場(chǎng)商業(yè)演出,只能聯(lián)系他的經(jīng)紀(jì)人。經(jīng)紀(jì)人會(huì)把商業(yè)演出的細(xì)節(jié)和報(bào)酬都談好之后,再把合同交給明星簽。
分類(lèi) 保護(hù)代理于控制不同權(quán)限的對(duì)象對(duì)目標(biāo)對(duì)象的訪問(wèn),如上面明星經(jīng)紀(jì)人的例子虛擬代理
把一些開(kāi)銷(xiāo)很大的對(duì)象,延遲到真正需要它的時(shí)候才去創(chuàng)建。 如短時(shí)間內(nèi)發(fā)起很多個(gè)http請(qǐng)求,我們可以用虛擬代理實(shí)現(xiàn)一定時(shí)間內(nèi)的請(qǐng)求統(tǒng)一發(fā)送優(yōu)缺點(diǎn) 優(yōu)點(diǎn)
1. 可以保護(hù)對(duì)象 2. 優(yōu)化性能,減少開(kāi)銷(xiāo)很大的對(duì)象 3. 緩存結(jié)果例子 圖片預(yù)加載 加載一張圖片
var myImage = (function () { var imgNode = document.createElement("img"); document.body.appendChild(imgNode); return { setSrc: function (src) { imgNode.src = src; } } })(); myImage.setSrc("https://segmentfault.com/img/bVbmvnB?w=573&h=158");
想象一下,如果我們的圖片很大,用戶就會(huì)看到頁(yè)面很長(zhǎng)一段時(shí)間是空白
我們可以想到的改進(jìn)是圖片加載完成之前都展示loading圖片
var myImage = (function () { var imgNode = document.createElement("img"); document.body.appendChild(imgNode); var img = new Image() img.onload = () => { // 模擬圖片加載 setTimeout(() => { imgNode.src = img.src }, 1000) } return { setSrc: function (src) { img.src = src imgNode.src = "https://content.igola.com/static/WEB/images/other/loading-searching.gif"; } } })(); myImage.setSrc("https://segmentfault.com/img/bVbmvnB?w=573&h=158");
這段代碼違背了單一職責(zé)原則,這個(gè)對(duì)象同時(shí)承擔(dān)了加載圖片和預(yù)加載圖片兩個(gè)職責(zé)
同時(shí)也違背了開(kāi)放封閉原則,如果我們以后不需要預(yù)加載圖片了,那我們不得不修改整個(gè)對(duì)象
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) { img.src = src myImage.setSrc("https://content.igola.com/static/WEB/images/other/loading-searching.gif") } } })() proxyImage.setSrc("https://segmentfault.com/img/bVbmvnB?w=573&h=158");
注意:我們的代理和本體接口要保持一致性,如上面proxyImage和myImage都返回一個(gè)包含setSrc方法的對(duì)象。居于這點(diǎn)我們寫(xiě)代理的時(shí)候也有跡可循。
虛擬代理合并HTTP請(qǐng)求 簡(jiǎn)單的實(shí)現(xiàn)1 2 3 4 5 6 7 8 9
缺點(diǎn)很明顯:每點(diǎn)一次就發(fā)送一次http請(qǐng)求
改進(jìn)緩存代理-計(jì)算乘積 粗糙的實(shí)現(xiàn)1 2 3 4 5 6 7 8 9
var mult = function () { console.log("開(kāi)始計(jì)算乘積"); var a = 1; for (var i = 0, l = arguments.length; i < l; i++) { a = a * arguments[i]; } return a; }; mult(2, 3); // 輸出:6 mult(2, 3, 4); // 輸出:24改進(jìn)
var mult = function () { console.log("開(kāi)始計(jì)算乘積"); var a = 1; for (var i = 0, l = arguments.length; i < l; i++) { a = a * arguments[i]; } return a; }; // mult(2, 3); // 輸出:6 // mult(2, 3, 4); // 輸出:24 var proxyMult = (function() { var cache = {} return function () { let id = Array.prototype.join.call(arguments, ",") if (cache[id]) { return cache[id] } else { return cache[id] = mult.apply(this, arguments) } } })() proxyMult(2, 3); // 輸出:6 proxyMult(2, 3); // 輸出:6
我們現(xiàn)在希望加法也能夠緩存
再改進(jìn)var mult = function () { console.log("開(kāi)始計(jì)算乘積"); var a = 1; for (var i = 0, l = arguments.length; i < l; i++) { a = a * arguments[i]; } return a; }; var plus = function () { console.log("開(kāi)始計(jì)算和"); var a = 0; for (var i = 0, l = arguments.length; i < l; i++) { a = a + arguments[i]; } return a; }; // mult(2, 3); // 輸出:6 // mult(2, 3, 4); // 輸出:24 var createProxyFactory = function (fn) { var cache = {} return function () { let id = Array.prototype.join.call(arguments, ",") if (cache[id]) { return cache[id] } else { return cache[id] = fn.apply(this, arguments) } } } var proxyMult = createProxyFactory(mult), proxyPlus = createProxyFactory(plus); proxyMult(1, 2, 3, 4) // 輸出:24 proxyMult(1, 2, 3, 4) // 輸出:24 proxyPlus(1, 2, 3, 4) // 輸出:10 proxyPlus(1, 2, 3, 4) // 輸出:10es6的代理模式 基于類(lèi)實(shí)現(xiàn)
class Car { drive() { return "driving"; }; } class CarProxy { constructor(driver) { this.driver = driver; } drive() { return ( this.driver.age < 18) ? "too young to drive" : new Car().drive(); }; } class Driver { constructor(age) { this.age = age; } }基于Proxy實(shí)現(xiàn)
// 明星 let star = { name: "張XX", age: 25, phone: "13910733521" } // 經(jīng)紀(jì)人 let agent = new Proxy(star, { get: function (target, key) { if (key === "phone") { // 返回經(jīng)紀(jì)人自己的手機(jī)號(hào) return "18611112222" } if (key === "price") { // 明星不報(bào)價(jià),經(jīng)紀(jì)人報(bào)價(jià) return 120000 } return target[key] }, set: function (target, key, val) { if (key === "customPrice") { if (val < 100000) { // 最低 10w throw new Error("價(jià)格太低") } else { target[key] = val return true } } } }) // 主辦方 console.log(agent.name) console.log(agent.age) console.log(agent.phone) console.log(agent.price) // 想自己提供報(bào)價(jià)(砍價(jià),或者高價(jià)爭(zhēng)搶?zhuān)?agent.customPrice = 150000 // agent.customPrice = 90000 // 報(bào)錯(cuò):價(jià)格太低 console.log("customPrice", agent.customPrice)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/100651.html
摘要:代理設(shè)計(jì)模式代理模式為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問(wèn)。代理模式是常見(jiàn)的設(shè)計(jì)模式之一是指不直接調(diào)用實(shí)際的對(duì)象,而是通過(guò)代理對(duì)象,來(lái)間接的調(diào)用實(shí)際的對(duì)象。對(duì)象類(lèi)定義了代理對(duì)象所代表的目標(biāo)對(duì)象。 代理設(shè)計(jì)模式 代理模式:為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問(wèn)。代理模式是常見(jiàn)的設(shè)計(jì)模式之一,是指不直接調(diào)用實(shí)際的對(duì)象,而是通過(guò)代理對(duì)象,來(lái)間接的調(diào)用實(shí)際的對(duì)象。為什么要采用這種間...
摘要:保護(hù)代理和虛擬代理保護(hù)代理當(dāng)有許多需求要向某對(duì)象發(fā)出一些請(qǐng)求時(shí),可以設(shè)置保護(hù)代理,通過(guò)一些條件判斷對(duì)請(qǐng)求進(jìn)行過(guò)濾。虛擬代理在程序中可以能有一些代價(jià)昂貴的操作。而虛擬代理是最常用的一種代理模式。 代理模式 代理模式是為一個(gè)對(duì)象提供一個(gè)代用品或占位符,以便控制對(duì)它的訪問(wèn)。 保護(hù)代理和虛擬代理 保護(hù)代理:當(dāng)有許多需求要向某對(duì)象發(fā)出一些請(qǐng)求時(shí),可以設(shè)置保護(hù)代理,通過(guò)一些條件判斷對(duì)請(qǐng)求進(jìn)行過(guò)濾。...
摘要:什么是代理模式代理模式,類(lèi)似于明星的經(jīng)紀(jì)人,想要拜訪明星,需要先通過(guò)經(jīng)紀(jì)人的溝通。不同于裝飾器,那種動(dòng)態(tài)加載一個(gè)對(duì)象,可以說(shuō)在代理模式當(dāng)中,代理是早已既定的。又稱(chēng)單一功能原則,面向?qū)ο笪鍌€(gè)基本原則之一。 什么是代理模式 代理模式,類(lèi)似于明星的經(jīng)紀(jì)人,想要拜訪明星,需要先通過(guò)經(jīng)紀(jì)人的溝通。而在JS當(dāng)中,如果想訪問(wèn)一個(gè)類(lèi),需要通過(guò)另一個(gè)類(lèi)來(lái)間接訪問(wèn) 。不同于裝飾器,那種動(dòng)態(tài)加載一個(gè)對(duì)象,可...
摘要:代理模式的定義為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問(wèn)。代理模式在客戶端和目標(biāo)對(duì)象之間起到一個(gè)中介作用,這樣可以起到保護(hù)目標(biāo)對(duì)象的作用。代理對(duì)象也可以對(duì)目標(biāo)對(duì)象調(diào)用之前進(jìn)行其他操作。 代理模式的定義:為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問(wèn)。在某些情況下,一個(gè)對(duì)象不適合或者不能直接引用另一個(gè)對(duì)象,而代理對(duì)象可以在客戶端和目標(biāo)對(duì)象之間起到中介的作用。 原文鏈接 虛擬代理 虛擬代理...
摘要:代理模式原文地址更多設(shè)計(jì)模式系列教程更多免費(fèi)教程博主按每天一個(gè)設(shè)計(jì)模式旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用靠這吃飯和純粹喜歡兩種語(yǔ)言實(shí)現(xiàn)。代理模式優(yōu)缺點(diǎn)代理模式有高度解耦對(duì)象保護(hù)易修改等優(yōu)點(diǎn)。 代理模式·原文地址 更多《設(shè)計(jì)模式系列教程》 更多免費(fèi)教程 博主按:《每天一個(gè)設(shè)計(jì)模式》旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用javascript(_靠這吃飯_)和python(_純粹喜歡_)...
摘要:代理模式原文地址更多設(shè)計(jì)模式系列教程更多免費(fèi)教程博主按每天一個(gè)設(shè)計(jì)模式旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用靠這吃飯和純粹喜歡兩種語(yǔ)言實(shí)現(xiàn)。代理模式優(yōu)缺點(diǎn)代理模式有高度解耦對(duì)象保護(hù)易修改等優(yōu)點(diǎn)。 代理模式·原文地址 更多《設(shè)計(jì)模式系列教程》 更多免費(fèi)教程 博主按:《每天一個(gè)設(shè)計(jì)模式》旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用javascript(_靠這吃飯_)和python(_純粹喜歡_)...
閱讀 1687·2021-09-26 10:00
閱讀 2945·2021-09-06 15:00
閱讀 3554·2021-09-04 16:40
閱讀 2327·2019-08-30 15:44
閱讀 731·2019-08-30 10:59
閱讀 1902·2019-08-29 18:34
閱讀 3630·2019-08-29 15:42
閱讀 2308·2019-08-29 15:36