享元(Flyweight)模式是一種經典的結構型設計模式,用於優化重覆、緩慢及數據共用效率較低的代碼。它旨在通過與相關對象共用儘可能多的數據來減少應用程式中記憶體的使用。 應用場景 (1)用於數據層,處理記憶體中保存的大量相似對象的共用數據。 (2)用於DOM層,Flyweight用作中央事件管理器,來 ...
享元(Flyweight)模式是一種經典的結構型設計模式,用於優化重覆、緩慢及數據共用效率較低的代碼。它旨在通過與相關對象共用儘可能多的數據來減少應用程式中記憶體的使用。
應用場景
(1)用於數據層,處理記憶體中保存的大量相似對象的共用數據。
(2)用於DOM層,Flyweight用作中央事件管理器,來避免將事件處理程式附加到父容器中的每個子元素上,而是將事件處理程式附加到這個父容器上。
示例
(1)用於數據層。管理圖書館中的所有書籍,享元優化。
// 每種書的數據,作為共用數據。 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; }; // 書籍單例,獲取共用數據(書籍)的方法。 var BookFactory = (function () { var existingBooks = {}, existingBook; return { createBook: function ( title, author, genre, pageCount, publisherID, ISBN ) { existingBook = existingBooks[ISBN]; if ( !!existingBook ) { return existingBook; } else { var book = new Book( title, author, genre, pageCount, publisherID, ISBN ); existingBooks[ISBN] = book; return book; } } }; })(); //書籍記錄管理器單例 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 ); } }; })();
每本書除了作為共用數據的書籍信息(內部數據)外,還有額外借出人、借出日期、歸還日期等外部數據,完全相同的書可以共用書籍信息。
(2)用於DOM層
HTML:
<div id="container"> <div class="toggle" href="#">More Info (Address) <span class="info"> This is more information </span></div> <div class="toggle" href="#">Even More Info (Map) <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>
JS:
var stateManager = { fly: function () { var self = this; $( "#container" ) .unbind() .on( "click", "div.toggle", function ( e ) { self.handleClick( e.target ); }); }, handleClick: function ( elem ) { elem.find( "span" ).toggle( "slow" ); } };
通常在構建我們自己的菜單、accordion組件或其他基於列表的小部件時,我們要做的就是將一個點擊事件綁定至父容器中的每個鏈接元素上。
其實不需將點擊綁定至多個元素,我們可以將享元附加到容器的頂部,它可以監聽來自下麵的事件。這樣的優點是,可以將很多獨立的動作轉變成一個共用的動作(可能會節省記憶體)。
總結
可能在寫前端代碼的時候,大家(包括我)都不會大註意記憶體的使用,有時的確存在冗餘對象,但因為影響不大,就不大註意。不過既然知道好的寫法是怎麼樣,我覺得可以這樣寫,養成一個好習慣。
參考文獻
1. 《JavaScript設計模式》by 徐濤【譯】
本文為原創文章,轉載請保留原出處,方便溯源,如有錯誤地方,謝謝指正。
本文地址 :http://www.cnblogs.com/lovesong/p/5700695.html