欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

輕松掌握J(rèn)avaScript享元模式

 更新時(shí)間:2016年08月27日 08:48:44   作者:蘇福  
這篇文章主要幫助大家輕松掌握J(rèn)avaScript享元模式,告訴大家想什么是js享元模式,感興趣的小伙伴們可以參考一下

在JavaScript中,瀏覽器特別是移動(dòng)端的瀏覽器分配的內(nèi)存很有限,如何節(jié)省內(nèi)存就成了一件非常有意義的事情。節(jié)省內(nèi)存的一個(gè)有效方法是減少對(duì)象的數(shù)量。 

享元模式(Flyweight),運(yùn)行共享技術(shù)有效地支持大量細(xì)粒度的對(duì)象,避免大量擁有相同內(nèi)容的小類的開銷(如耗費(fèi)內(nèi)存),使大家共享一個(gè)類(元類)。 

享元模式可以避免大量非常相似類的開銷,在程序設(shè)計(jì)中,有時(shí)需要生產(chǎn)大量細(xì)粒度的類實(shí)例來表示數(shù)據(jù),如果能發(fā)現(xiàn)這些實(shí)例除了幾個(gè)參數(shù)以外,開銷基本相同的話,就可以大幅度較少需要實(shí)例化的類的數(shù)量。如果能把那些參數(shù)移動(dòng)到類實(shí)例的外面,在方法調(diào)用的時(shí)候?qū)⑺麄儌鬟f進(jìn)來,就可以通過共享大幅度第減少單個(gè)實(shí)例 的數(shù)目。 

在JavaScript中應(yīng)用享元模式有兩種方式,第一種是應(yīng)用在數(shù)據(jù)層上,主要是應(yīng)用在內(nèi)存里大量相似的對(duì)象上;第二種是應(yīng)用在DOM層上,享元可以用在中央事件管理器上用來避免給父容器里的每個(gè)子元素都附加事件句柄 

Flyweight中有兩個(gè)重要概念--內(nèi)部狀態(tài)intrinsic和外部狀態(tài)extrinsic之分,內(nèi)部狀態(tài)就是在對(duì)象里通過內(nèi)部方法管理,而外部信息可以在通過外部刪除或者保存。 

說白點(diǎn),就是先捏一個(gè)的原始模型,然后隨著不同場(chǎng)合和環(huán)境,再產(chǎn)生各具特征的具體模型,很顯然,在這里需要產(chǎn)生不同的新對(duì)象,所以Flyweight模式中常出現(xiàn)Factory模式,F(xiàn)lyweight的內(nèi)部狀態(tài)是用來共享的,F(xiàn)lyweight factory負(fù)責(zé)維護(hù)一個(gè)Flyweight pool(模式池)來存放內(nèi)部狀態(tài)的對(duì)象。 

我們可以將內(nèi)部狀態(tài)相同的所有對(duì)象替換為同一個(gè)共享對(duì)象,而要?jiǎng)?chuàng)建這樣一個(gè)共享對(duì)象就需要用到單例工廠方法,而不是普通的構(gòu)造函數(shù),這樣做可以跟蹤到已經(jīng)實(shí)例化的各個(gè)對(duì)象,從而僅當(dāng)所需對(duì)象的內(nèi)部狀態(tài)不同于已有對(duì)象時(shí)才創(chuàng)建一個(gè)新對(duì)象。對(duì)象的外在狀態(tài)被保存在一個(gè)管理器對(duì)象中。在調(diào)用對(duì)象的方法時(shí),管理器會(huì)把這些外在狀態(tài)作為參數(shù)傳入。 

把一個(gè)對(duì)象的數(shù)據(jù)保存在兩個(gè)不同的對(duì)象中(共享對(duì)象、管理器對(duì)象)
 1.共享對(duì)象(享元對(duì)象)
 2.單例工廠方法(創(chuàng)建共享對(duì)象)
 3.管理器對(duì)象(管理外部狀態(tài)) 

比如圖書館中的一本書可以用一個(gè)對(duì)象來表示,他有很多屬性

 var Book = function( id, title, author, genre, pageCount,publisherID, ISBN, checkoutDate, checkoutMember, dueReturnDate,availability ){
  ...//初始化代碼
}
Book.prototype = {
  getTitle:function(){
    return this.title;
  },
  ...
  // 更新借出狀態(tài)方法
  updateCheckoutStatus:function(bookID, newStatus, checkoutDate,checkoutMember, newReturnDate){...},
  //續(xù)借
  extendCheckoutPeriod: function(bookID, newReturnDate){...},
  //是否到期
  isPastDue: function(bookID){...}
} 

程序剛開始可能沒問題,但是隨著時(shí)間的增加,圖書可能大批量增加,并且每種圖書都有不同的版本和數(shù)量,你將會(huì)發(fā)現(xiàn)系統(tǒng)變得越來越慢。幾千個(gè)book對(duì)象在內(nèi)存里可想而知,我們需要用享元模式來優(yōu)化。 

我們可以將數(shù)據(jù)分成內(nèi)部和外部?jī)煞N數(shù)據(jù),同一本書中,和book對(duì)象相關(guān)的數(shù)據(jù)(title,author等)可以歸結(jié)為內(nèi)部屬性,而(checkoutMember,dueReturnDate等)可以歸結(jié)為外部屬性。這樣,如下代碼就可以在同一本書里共享同一個(gè)對(duì)象了,因?yàn)椴还苷l借的書,只要書是同一本書,基本信息是一樣的:

 //共享對(duì)象
var Book = function(title, author, genre, pageCount, publisherID, ISBN){
  this.title = title;
  this.author = author;
  this.genre = genre;
  this.pageCount = pageCount;
  this.publisherID = publisherID;
  this.ISBN = ISBN;
}; 

讓我們來定義一個(gè)基本工廠,用來檢查之前是否創(chuàng)建該book的對(duì)象,如果有就返回,沒有就重新創(chuàng)建并存儲(chǔ)以便后面可以繼續(xù)訪問,這確保我們?yōu)槊恳环N書只創(chuàng)建一個(gè)對(duì)象:

 /* Book工廠 單例 */
var BookFactory = (function(){
  var existingBooks = {};
  return{
    createBook: function(title, author, genre,pageCount,publisherID,ISBN){
    /*查找之前是否創(chuàng)建*/
      var existingBook = existingBooks[ISBN];
      if(existingBook){
        return existingBook;
      }else{
        /* 如果沒有,就創(chuàng)建一個(gè),然后保存*/
        var book = new Book(title, author, genre,pageCount,publisherID,ISBN);
        existingBooks[ISBN] = book;
        return book;
      }
    }
  }
}); 

外部狀態(tài),相對(duì)就簡(jiǎn)單了,除了我們封裝好的book,其它都需要在這里管理:

 /*BookRecordManager 借書管理類 單例*/
var BookRecordManager = (function(){
  var bookRecordDatabase = {};
  return{
    /*添加借書記錄*/
    addBookRecord: function(id, title, author, genre,pageCount,publisherID,ISBN, checkoutDate, checkoutMember, dueReturnDate, availability){
      var book = bookFactory.createBook(title, author, genre,pageCount,publisherID,ISBN);
      bookRecordDatabase[id] ={
        checkoutMember: checkoutMember,
        checkoutDate: checkoutDate,
        dueReturnDate: dueReturnDate,
        availability: availability,
        book: book;
      };
    },
    updateCheckoutStatus: function(bookID, newStatus, checkoutDate, checkoutMember, newReturnDate){
      var record = bookRecordDatabase[bookID];
      record.availability = newStatus;
      record.checkoutDate = checkoutDate;
      record.checkoutMember = checkoutMember;
      record.dueReturnDate = newReturnDate;
    },
    extendCheckoutPeriod: function(bookID, newReturnDate){
      bookRecordDatabase[bookID].dueReturnDate = newReturnDate;
    },
    isPastDue: function(bookID){
      var currentDate = new Date();
      return currentDate.getTime() > Date.parse(bookRecordDatabase[bookID].dueReturnDate);
    }
  };
}); 

通過這種方式,我們做到了將同一種圖書的相同信息保存在一個(gè)bookmanager對(duì)象里,而且只保存一份;相比之前的代碼,就可以發(fā)現(xiàn)節(jié)約了很多內(nèi)存。 

對(duì)象池 
對(duì)象池是另外一種性能優(yōu)化方案,和享元模式有一些相似之處,但沒有分離內(nèi)部狀態(tài)和外部狀態(tài)這個(gè)過程。 
通用對(duì)象池實(shí)現(xiàn):

 var objectPoolFactory = function (createObjFn) {
  var objectPool = []; //對(duì)象池
  return {
    create: function () { //取出
      var obj = objectPool.length === 0 ? createObjFn.apply(this,arguments) : objectPool.shift();
      return obj;
    },
    recover: function (obj) { //收回
      objectPool.push(obj);
    }
  }
}; 

現(xiàn)在利用objectPoolFactory來創(chuàng)建一個(gè)裝載一些iframe的對(duì)象池:

 var iframeFactory = objectPoolFactory(function () {
  var iframe = document.createElement('iframe');
  document.body.appendChild(iframe);
  iframe.onload = function () {
    iframe.onload = null; //防止iframe重復(fù)加載的bug
    iframeFactory.recover(iframe); //iframe加載完成后往對(duì)象池填回節(jié)點(diǎn)(收回)
  };
  return iframe;
});
//調(diào)用
var iframe1 = iframeFactory.create();
iframe1.src = 'http://www.qq.com'; 

參考文獻(xiàn): 《JavaScript模式》 《JavaScript設(shè)計(jì)模式與開發(fā)實(shí)踐》

 以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • JS ES6異步解決方案

    JS ES6異步解決方案

    這篇文章主要介紹了JS ES6異步解決方案,對(duì)異步感興趣的同學(xué),可以參考下
    2021-04-04
  • JavaScript實(shí)現(xiàn)簡(jiǎn)易飛機(jī)大戰(zhàn)

    JavaScript實(shí)現(xiàn)簡(jiǎn)易飛機(jī)大戰(zhàn)

    這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)簡(jiǎn)易飛機(jī)大戰(zhàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • javascript中的this詳解

    javascript中的this詳解

    avaScript 中的 this 關(guān)鍵字,深入淺出的分析其在不同情況下的含義,形成這種情況的原因以及 Dojo 等 JavaScript 工具中提供的綁定 this 的方法??梢赃@樣說,正確掌握了 JavaScript 中的 this 關(guān)鍵字,才算邁入了 JavaScript 這門語言的門檻。
    2014-12-12
  • 基于layui數(shù)據(jù)表格以及傳數(shù)據(jù)的方式

    基于layui數(shù)據(jù)表格以及傳數(shù)據(jù)的方式

    今天小編就為大家分享一篇基于layui數(shù)據(jù)表格以及傳數(shù)據(jù)的方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-08-08
  • JavaScript限定范圍拖拽及自定義滾動(dòng)條應(yīng)用(3)

    JavaScript限定范圍拖拽及自定義滾動(dòng)條應(yīng)用(3)

    這篇文章主要介紹了JavaScript限定范圍拖拽及自定義滾動(dòng)條應(yīng)用的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • JS實(shí)現(xiàn)留言板功能[樓層效果展示]

    JS實(shí)現(xiàn)留言板功能[樓層效果展示]

    小編最近在基于js實(shí)現(xiàn)留言板功能,實(shí)現(xiàn)的功能有發(fā)布人和發(fā)布內(nèi)容做非空校驗(yàn),樓層效果展示和發(fā)布時(shí)間展示。具體實(shí)例代碼大家參考下本文
    2017-12-12
  • JavaScript駕馭網(wǎng)頁-DOM

    JavaScript駕馭網(wǎng)頁-DOM

    這篇文章主要介紹了JavaScript駕馭網(wǎng)頁-DOM的相關(guān)資料,需要的朋友可以參考下
    2016-03-03
  • JavaScript 消息框效果【實(shí)現(xiàn)代碼】

    JavaScript 消息框效果【實(shí)現(xiàn)代碼】

    下面小編就為大家?guī)硪黄狫avaScript 消息框效果【實(shí)現(xiàn)代碼】。小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考
    2016-04-04
  • 幾種延遲加載JS代碼的方法加快網(wǎng)頁的訪問速度

    幾種延遲加載JS代碼的方法加快網(wǎng)頁的訪問速度

    如何延遲javascript代碼的加載,加快網(wǎng)頁的訪問速度,為了讓我們的網(wǎng)頁加載速度更快,本文總結(jié)了一下幾個(gè)注意點(diǎn),感興趣的朋友可以參考下
    2013-10-10
  • javascript中export?和export?default的區(qū)別

    javascript中export?和export?default的區(qū)別

    本文主要介紹了javascript中export?和export?default的區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07

最新評(píng)論