成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

js設(shè)計(jì)模式--代理模式

pubdreamcc / 2107人閱讀

摘要:文章系列設(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圖片

加個(gè)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ì)象

用虛擬代理改進(jìn)
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)

  
1 2 3 4 5 6 7 8 9
緩存代理-計(jì)算乘積 粗糙的實(shí)現(xià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
改進(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) // 輸出:10
es6的代理模式 基于類(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

相關(guān)文章

  • js設(shè)計(jì)模式 --- 代理設(shè)計(jì)模式

    摘要:代理設(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ì)象。為什么要采用這種間...

    Tonny 評(píng)論0 收藏0
  • JS代理模式《JavaScript設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐》閱讀筆記

    摘要:保護(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ò)濾。...

    mist14 評(píng)論0 收藏0
  • JS設(shè)計(jì)模式代理模式

    摘要:什么是代理模式代理模式,類(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ì)象,可...

    widuu 評(píng)論0 收藏0
  • JS設(shè)計(jì)模式-代理模式

    摘要:代理模式的定義為其他對(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ì)象之間起到中介的作用。 原文鏈接 虛擬代理 虛擬代理...

    馬龍駒 評(píng)論0 收藏0
  • 每天一個(gè)設(shè)計(jì)模式·代理模式

    摘要:代理模式原文地址更多設(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(_純粹喜歡_)...

    XiNGRZ 評(píng)論0 收藏0
  • 每天一個(gè)設(shè)計(jì)模式·代理模式

    摘要:代理模式原文地址更多設(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(_純粹喜歡_)...

    MasonEast 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<