亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 語言 > JavaScript > 正文

深入理解JavaScript系列(37):設計模式之享元模式詳解

2024-05-06 16:15:57
字體:
來源:轉載
供稿:網友
這篇文章主要介紹了深入理解JavaScript系列(37):設計模式之享元模式詳解,享元模式(Flyweight),運行共享技術有效地支持大量細粒度的對象,避免大量擁有相同內容的小類的開銷(如耗費內存),使大家共享一個類(元類),需要的朋友可以參考下
 

介紹

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

享元模式可以避免大量非常相似類的開銷,在程序設計中,有時需要生產大量細粒度的類實例來表示數據,如果能發現這些實例除了幾個參數以外,開銷基本相同的 話,就可以大幅度較少需要實例化的類的數量。如果能把那些參數移動到類實例的外面,在方法調用的時候將他們傳遞進來,就可以通過共享大幅度第減少單個實例 的數目。

那么如果在JavaScript中應用享元模式呢?有兩種方式,第一種是應用在數據層上,主要是應用在內存里大量相似的對象上;第二種是應用在DOM層上,享元可以用在中央事件管理器上用來避免給父容器里的每個子元素都附加事件句柄。

享元與數據層

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

說白點,就是先捏一個的原始模型,然后隨著不同場合和環境,再產生各具特征的具體模型,很顯然,在這里需要產生不同的新對象,所以Flyweight模式中常出現Factory模式,Flyweight的內部狀態是用來共享的,Flyweight factory負責維護一個Flyweight pool(模式池)來存放內部狀態的對象。

使用享元模式

讓我們來演示一下如果通過一個類庫讓系統來管理所有的書籍,每個書籍的元數據暫定為如下內容:

復制代碼代碼如下:

ID
Title
Author
Genre
Page count
Publisher ID
ISBN

我們還需要定義每本書被借出去的時間和借書人,以及退書日期和是否可用狀態:
復制代碼代碼如下:

checkoutDate
checkoutMember
dueReturnDate
availability

因為book對象設置成如下代碼,注意該代碼還未被優化:
復制代碼代碼如下:

var Book = function( id, title, author, genre, pageCount,publisherID, ISBN, checkoutDate, checkoutMember, dueReturnDate,availability ){
   this.id = id;
   this.title = title;
   this.author = author;
   this.genre = genre;
   this.pageCount = pageCount;
   this.publisherID = publisherID;
   this.ISBN = ISBN;
   this.checkoutDate = checkoutDate;
   this.checkoutMember = checkoutMember;
   this.dueReturnDate = dueReturnDate;
   this.availability = availability;
};
Book.prototype = {
   getTitle:function(){
       return this.title;
   },
   getAuthor: function(){
       return this.author;
   },
   getISBN: function(){
       return this.ISBN;
   },
/*其它get方法在這里就不顯示了*/

 

// 更新借出狀態
updateCheckoutStatus: function(bookID, newStatus, checkoutDate,checkoutMember, newReturnDate){
   this.id  = bookID;
   this.availability = newStatus;
   this.checkoutDate = checkoutDate;
   this.checkoutMember = checkoutMember;
   this.dueReturnDate = newReturnDate;
},
//續借
extendCheckoutPeriod: function(bookID, newReturnDate){
    this.id =  bookID;
    this.dueReturnDate = newReturnDate;
},
//是否到期
isPastDue: function(bookID){
   var currentDate = new Date();
   return currentDate.getTime() > Date.parse(this.dueReturnDate);
 }
};


程序剛開始可能沒問題,但是隨著時間的增加,圖書可能大批量增加,并且每種圖書都有不同的版本和數量,你將會發現系統變得越來越慢。幾千個book對象在內存里可想而知,我們需要用享元模式來優化。

 

我們可以將數據分成內部和外部兩種數據,和book對象相關的數據(title, author 等)可以歸結為內部屬性,而(checkoutMember, dueReturnDate等)可以歸結為外部屬性。這樣,如下代碼就可以在同一本書里共享同一個對象了,因為不管誰借的書,只要書是同一本書,基本信息是一樣的:

復制代碼代碼如下:

/*享元模式優化代碼*/
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;
};

 

定義基本工廠

讓我們來定義一個基本工廠,用來檢查之前是否創建該book的對象,如果有就返回,沒有就重新創建并存儲以便后面可以繼續訪問,這確保我們為每一種書只創建一個對象:

復制代碼代碼如下:

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

管理外部狀態
外部狀態,相對就簡單了,除了我們封裝好的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);
   }
 };
});


通過這種方式,我們做到了將同一種圖書的相同信息保存在一個bookmanager對象里,而且只保存一份;相比之前的代碼,就可以發現節約了很多內存。

 

享元模式與DOM

關于DOM的事件冒泡,在這里就不多說了,相信大家都已經知道了,我們舉兩個例子。

例1:事件集中管理

舉例來說,如果我們又很多相似類型的元素或者結構(比如菜單,或者ul里的多個li)都需要監控他的click事件的話,那就需要多每個元素進行事件綁定,如果元素有非常非常多,那性能就可想而知了,而結合冒泡的知識,任何一個子元素有事件觸發的話,那觸發以后事件將冒泡到上一級元素,所以利用這個特性,我們可以使用享元模式,我們可以對這些相似元素的父級元素進行事件監控,然后再判斷里面哪個子元素有事件觸發了,再進行進一步的操作。

在這里我們結合一下jQuery的bind/unbind方法來舉例。

HTML:

復制代碼代碼如下:

<div id="container">
   <div class="toggle" href="#">更多信息 (地址)
       <span class="info">
          這里是更多信息
       </span></div>
   <div class="toggle" href="#">更多信息 (地圖)
       <span class="info">
          <iframe src="http://www.map-generator.net/extmap.php?name=London&address=london%2C%20england&width=500...gt;"</iframe>
       </span>
   </div>
</div>

JavaScript:
復制代碼代碼如下:

stateManager = {
   fly: function(){
       var self =  this;
       $('#container').unbind().bind("click", function(e){
           var target = $(e.originalTarget || e.srcElement);
           // 判斷是哪一個子元素
           if(target.is("div.toggle")){
               self.handleClick(target);
           }
       });
   },

 

   handleClick: function(elem){
       elem.find('span').toggle('slow');
   }
});

 

例2:應用享元模式提升性能

另外一個例子,依然和jQuery有關,一般我們在事件的回調函數里使用元素對象是會后,經常會用到$(this)這種形式,其實它重復創建了新對象,因為本身回調函數里的this已經是DOM元素自身了,我們必要必要使用如下這樣的代碼:

復制代碼代碼如下:

$('div').bind('click', function(){
 console.log('You clicked: ' + $(this).attr('id'));
});
// 上面的代碼,要避免使用,避免再次對DOM元素進行生成jQuery對象,因為這里可以直接使用DOM元素自身了。
$('div').bind('click', function(){
 console.log('You clicked: ' + this.id);
});

其實,如果非要用$(this)這樣的形式,我們也可以實現自己版本的單實例模式,比如我們來實現一個jQuery.signle(this)這樣的函數以便返回DOM元素自身:
復制代碼代碼如下:

jQuery.single = (function(o){

 

   var collection = jQuery([1]);
   return function(element) {

       // 將元素放到集合里
       collection[0] = element;

        // 返回集合
       return collection;

   };
 });
 


使用方法:
復制代碼代碼如下:

$('div').bind('click', function(){
   var html = jQuery.single(this).next().html();
   console.log(html);
 });

這樣,就是原樣返回DOM元素自身了,而且不進行jQuery對象的創建。

 

總結

Flyweight模式是一個提高程序效率和性能的模式,會大大加快程序的運行速度.應用場合很多:比如你要從一個數據庫中讀取一系列字符串,這些字符串中有許多是重復的,那么我們可以將這些字符串儲存在Flyweight池(pool)中。

如果一個應用程序使用了大量的對象,而這些大量的對象造成了很大的存儲開心時就應該考慮使用享元模式;還有就是對象的大多數狀態可以外部狀態,如果刪除對象的外部狀態,那么就可以用相對較少的共享對象取代很多組對象,此時可以考慮使用享元模式。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
美日韩在线视频| 久久久久久久影院| 国产福利视频一区| 成人黄色影片在线| 青青久久av北条麻妃黑人| 一区三区二区视频| 日韩av综合中文字幕| 欧美大尺度电影在线观看| 日韩精品免费综合视频在线播放| 精品国产区一区二区三区在线观看| 国产日韩在线看| 欧美乱人伦中文字幕在线| 日韩精品免费观看| 国产美女91呻吟求| 亚洲另类图片色| 国产一区二区日韩| 亚洲精品自在久久| 欧美一区二粉嫩精品国产一线天| 国产精品你懂得| 亚洲人成电影网站| 热re91久久精品国99热蜜臀| 欧美性高潮床叫视频| 精品调教chinesegay| 91精品国产91久久久久久吃药| 国产69精品久久久久9999| 精品视频偷偷看在线观看| 91精品国产91久久久久久| 亚洲电影中文字幕| 日韩毛片在线观看| 国产精品一区二区久久精品| 亚洲精品午夜精品| 成人国产精品一区| 亚洲福利视频久久| 成人黄色免费片| 中文字幕欧美在线| 亚洲欧美变态国产另类| 欧美亚洲日本黄色| 日韩视频免费在线观看| 日韩精品视频在线观看网址| 日韩av在线高清| 日韩欧美在线一区| 亚洲男人天天操| 乱亲女秽乱长久久久| 岛国视频午夜一区免费在线观看| 51ⅴ精品国产91久久久久久| 亚洲第一在线视频| 欧美国产在线视频| 日韩欧美在线国产| 国产亚洲精品va在线观看| 欧美精品久久久久久久久| 欧美一级视频一区二区| 1769国内精品视频在线播放| 国产剧情久久久久久| 亚洲一区二区三区成人在线视频精品| 中文字幕亚洲自拍| 成人做爰www免费看视频网站| 自拍视频国产精品| www.日韩欧美| 国产精品一区二区三区成人| 国产精品久久久久久久久久新婚| 欧美日韩国产激情| 久久久久久久久久久亚洲| 欧美综合在线观看| 色偷偷91综合久久噜噜| 91牛牛免费视频| 亚洲成人av在线播放| 国产精品96久久久久久又黄又硬| 爱福利视频一区| 久久久久久香蕉网| 精品久久香蕉国产线看观看gif| 中文字幕久精品免费视频| 日本国产精品视频| 午夜精品一区二区三区在线| 韩国精品美女www爽爽爽视频| 日韩视频免费在线观看| 精品久久久国产精品999| 国产精品入口尤物| 欧美激情a∨在线视频播放| 中文字幕日韩电影| 国产中文字幕91| 国产日本欧美一区| 最近2019年中文视频免费在线观看| 成人a视频在线观看| 国产欧美一区二区三区视频| 中文字幕欧美视频在线| 久久久久久国产| 亚洲国产日韩欧美综合久久| 久久久久久久久久久人体| 日韩欧美高清视频| 九九久久久久久久久激情| 久久激情视频久久| 亚洲男人7777| 欧美性猛交xxxx久久久| 国产视频精品xxxx| 4438全国成人免费| 国产成人一区二区| 91精品视频在线免费观看| 国产精品高清网站| 91国产高清在线| 欧美韩国理论所午夜片917电影| 成年人精品视频| 久久这里有精品视频| 国产成人综合精品在线| 庆余年2免费日韩剧观看大牛| 国产91亚洲精品| 日韩av网站大全| 久久精品视频亚洲| 日韩激情第一页| 久久精品这里热有精品| 国产成人精彩在线视频九色| 色悠久久久久综合先锋影音下载| 国产精品999999| 亚洲综合av影视| 欧美成人亚洲成人日韩成人| 91影视免费在线观看| 亚洲无av在线中文字幕| 91丨九色丨国产在线| 欧美怡春院一区二区三区| 亚洲成人亚洲激情| 日韩女在线观看| 亚洲精品白浆高清久久久久久| 国模精品视频一区二区三区| 一区二区欧美日韩视频| 国产精品久久久久久久久久久新郎| 欧美综合激情网| 欧美孕妇毛茸茸xxxx| 91国产精品91| 91av免费观看91av精品在线| 亚洲天堂开心观看| 亚洲福利在线视频| 欧美理论片在线观看| 亚洲成色777777女色窝| 美女少妇精品视频| 欧美成人在线影院| 亚洲日韩中文字幕在线播放| 日韩精品免费看| 久久久久免费精品国产| 久久精品在线播放| 欧美激情va永久在线播放| 精品在线小视频| 日韩电影中文 亚洲精品乱码| 久久影院资源网| 亚洲无av在线中文字幕| 精品国产老师黑色丝袜高跟鞋| 亚洲国产日韩一区| 久久中文字幕一区| 欧美日韩国产精品| xx视频.9999.com| 九九热这里只有精品免费看| 欧美日韩xxxxx| 欧美性猛xxx| 久久精品视频在线| 日韩欧美在线视频免费观看| 欧美精品手机在线| 中文字幕久热精品视频在线| 91国在线精品国内播放| 欧美中文在线视频| 国产欧美在线看| 国产精品狼人色视频一区| 91精品国产高清久久久久久91| 国产精品国产亚洲伊人久久| 一区二区中文字幕| 国产女人精品视频| 精品视频久久久久久|