摘要:文章系列設計模式單例模式設計模式策略模式設計模式代理模式概念代理模式是為一個對象提供一個代用品或占位符,以便控制對它的訪問。
前言
本系列文章主要根據《JavaScript設計模式與開發實踐》整理而來,其中會加入了一些自己的思考。希望對大家有所幫助。
文章系列js設計模式--單例模式
js設計模式--策略模式
js設計模式--代理模式
概念代理模式是為一個對象提供一個代用品或占位符,以便控制對它的訪問。
UML類圖 場景比如,明星都有經紀人作為代理。如果想請明星來辦一場商業演出,只能聯系他的經紀人。經紀人會把商業演出的細節和報酬都談好之后,再把合同交給明星簽。
分類 保護代理于控制不同權限的對象對目標對象的訪問,如上面明星經紀人的例子虛擬代理
把一些開銷很大的對象,延遲到真正需要它的時候才去創建。 如短時間內發起很多個http請求,我們可以用虛擬代理實現一定時間內的請求統一發送優缺點 優點
1. 可以保護對象 2. 優化性能,減少開銷很大的對象 3. 緩存結果例子 圖片預加載 加載一張圖片
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");
想象一下,如果我們的圖片很大,用戶就會看到頁面很長一段時間是空白
我們可以想到的改進是圖片加載完成之前都展示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");
這段代碼違背了單一職責原則,這個對象同時承擔了加載圖片和預加載圖片兩個職責
同時也違背了開放封閉原則,如果我們以后不需要預加載圖片了,那我們不得不修改整個對象
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都返回一個包含setSrc方法的對象。居于這點我們寫代理的時候也有跡可循。
虛擬代理合并HTTP請求 簡單的實現1 2 3 4 5 6 7 8 9
缺點很明顯:每點一次就發送一次http請求
改進緩存代理-計算乘積 粗糙的實現1 2 3 4 5 6 7 8 9
var mult = function () { console.log("開始計算乘積"); 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 mult = function () { console.log("開始計算乘積"); 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
我們現在希望加法也能夠緩存
再改進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 plus = function () { console.log("開始計算和"); 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的代理模式 基于類實現
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實現
// 明星 let star = { name: "張XX", age: 25, phone: "13910733521" } // 經紀人 let agent = new Proxy(star, { get: function (target, key) { if (key === "phone") { // 返回經紀人自己的手機號 return "18611112222" } if (key === "price") { // 明星不報價,經紀人報價 return 120000 } return target[key] }, set: function (target, key, val) { if (key === "customPrice") { if (val < 100000) { // 最低 10w throw new Error("價格太低") } else { target[key] = val return true } } } }) // 主辦方 console.log(agent.name) console.log(agent.age) console.log(agent.phone) console.log(agent.price) // 想自己提供報價(砍價,或者高價爭搶) agent.customPrice = 150000 // agent.customPrice = 90000 // 報錯:價格太低 console.log("customPrice", agent.customPrice)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/100651.html
摘要:代理設計模式代理模式為其他對象提供一種代理以控制對這個對象的訪問。代理模式是常見的設計模式之一是指不直接調用實際的對象,而是通過代理對象,來間接的調用實際的對象。對象類定義了代理對象所代表的目標對象。 代理設計模式 代理模式:為其他對象提供一種代理以控制對這個對象的訪問。代理模式是常見的設計模式之一,是指不直接調用實際的對象,而是通過代理對象,來間接的調用實際的對象。為什么要采用這種間...
摘要:保護代理和虛擬代理保護代理當有許多需求要向某對象發出一些請求時,可以設置保護代理,通過一些條件判斷對請求進行過濾。虛擬代理在程序中可以能有一些代價昂貴的操作。而虛擬代理是最常用的一種代理模式。 代理模式 代理模式是為一個對象提供一個代用品或占位符,以便控制對它的訪問。 保護代理和虛擬代理 保護代理:當有許多需求要向某對象發出一些請求時,可以設置保護代理,通過一些條件判斷對請求進行過濾。...
摘要:什么是代理模式代理模式,類似于明星的經紀人,想要拜訪明星,需要先通過經紀人的溝通。不同于裝飾器,那種動態加載一個對象,可以說在代理模式當中,代理是早已既定的。又稱單一功能原則,面向對象五個基本原則之一。 什么是代理模式 代理模式,類似于明星的經紀人,想要拜訪明星,需要先通過經紀人的溝通。而在JS當中,如果想訪問一個類,需要通過另一個類來間接訪問 。不同于裝飾器,那種動態加載一個對象,可...
摘要:代理模式的定義為其他對象提供一種代理以控制對這個對象的訪問。代理模式在客戶端和目標對象之間起到一個中介作用,這樣可以起到保護目標對象的作用。代理對象也可以對目標對象調用之前進行其他操作。 代理模式的定義:為其他對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個對象不適合或者不能直接引用另一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用。 原文鏈接 虛擬代理 虛擬代理...
摘要:代理模式原文地址更多設計模式系列教程更多免費教程博主按每天一個設計模式旨在初步領會設計模式的精髓,目前采用靠這吃飯和純粹喜歡兩種語言實現。代理模式優缺點代理模式有高度解耦對象保護易修改等優點。 代理模式·原文地址 更多《設計模式系列教程》 更多免費教程 博主按:《每天一個設計模式》旨在初步領會設計模式的精髓,目前采用javascript(_靠這吃飯_)和python(_純粹喜歡_)...
摘要:代理模式原文地址更多設計模式系列教程更多免費教程博主按每天一個設計模式旨在初步領會設計模式的精髓,目前采用靠這吃飯和純粹喜歡兩種語言實現。代理模式優缺點代理模式有高度解耦對象保護易修改等優點。 代理模式·原文地址 更多《設計模式系列教程》 更多免費教程 博主按:《每天一個設計模式》旨在初步領會設計模式的精髓,目前采用javascript(_靠這吃飯_)和python(_純粹喜歡_)...
閱讀 1671·2021-09-26 10:00
閱讀 2935·2021-09-06 15:00
閱讀 3537·2021-09-04 16:40
閱讀 2297·2019-08-30 15:44
閱讀 714·2019-08-30 10:59
閱讀 1882·2019-08-29 18:34
閱讀 3615·2019-08-29 15:42
閱讀 2292·2019-08-29 15:36