introduce
The Flyweight mode (Flyweight) runs sharing technology to effectively support a large number of fine-grained objects, avoiding the overhead of a large number of small classes with the same content (such as memory consumption), and allowing everyone to share a class (metaclass).
The Encyclopedia pattern can avoid a large amount of overhead of very similar classes. In programming, it is sometimes necessary to produce a large number of fine-grained class instances to represent data. If you can find that these instances have basically the same overhead except for a few parameters, you can significantly reduce the number of classes that need to be instantiated. If those parameters can be moved outside the class instance and passed them in when the method is called, the number of individual instances can be greatly reduced by sharing.
So what if you apply the Encyclopedia Mode in JavaScript? There are two ways. The first is to apply it to the data layer, mainly to a large number of similar objects in memory; the second is to apply it to the DOM layer, which can be used on the central event manager to avoid adding event handles to each child element in the parent container.
Enjoy the data layer
There are two important concepts in Flyweight - internal state intrinsic and external state extrinsic. Internal state is managed through internal methods in the object, and external information can be deleted or saved externally.
To put it bluntly, it is to first pinch an original model, and then produce specific models with different characteristics according to different occasions and environments. Obviously, different new objects need to be generated here, so Factory mode often appears in the Flyweight mode. The internal state of Flyweight is used to share. Flyweight factory is responsible for maintaining a Flyweight pool (mode pool) to store objects with internal state.
Use the Enjoyment Mode
Let's demonstrate that if the system uses a class library to manage all books, the metadata of each book is tentatively set to the following content:
The code copy is as follows:
ID
Title
Author
Genre
Page count
Publisher ID
ISBN
We also need to define the time and borrower of each book, as well as the date of return and whether it is available:
The code copy is as follows:
checkoutDate
checkoutMember
dueReturnDate
availability
Because the book object is set to the following code, please note that the code has not been optimized yet:
The code copy is as follows:
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;
},
/*Other get methods will not be displayed here*/
// Update the lending status
updateCheckoutStatus: function(bookID, newStatus, checkoutDate,checkoutMember, newReturnDate){
this.id = bookID;
this.availability = newStatus;
this.checkoutDate = checkoutDate;
this.checkoutMember = checkoutMember;
this.dueReturnDate = newReturnDate;
},
//renew
extendCheckoutPeriod: function(bookID, newReturnDate){
this.id = bookID;
this.dueReturnDate = newReturnDate;
},
//Is it expired
isPastDue: function(bookID){
var currentDate = new Date();
return currentDate.getTime() > Date.parse(this.dueReturnDate);
}
};
The program may be fine at the beginning, but as time goes by, books may increase in large quantities, and each type of book has different versions and quantities, you will find that the system is getting slower and slower. Thousands of book objects can be imagined in memory, and we need to use the Encyclopedia mode to optimize.
We can divide the data into two types of internal and external data. The data related to book objects (title, author, etc.) can be attributed to internal properties, while (checkoutMember, dueReturnDate, etc.) can be attributed to external properties. In this way, the following code can share the same object in the same book, because no matter who borrows the book, as long as the book is the same book, the basic information is the same:
The code copy is as follows:
/*Xienyuan mode optimization code*/
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;
};
Defining the base factory
Let's define a basic factory to check whether the object of the book was created before, return if there is, and recreate and store it so that it can continue to access later, which ensures that we only create one object for each book:
The code copy is as follows:
/* Book Factory Singleton*/
var BookFactory = (function(){
var existingBooks = {};
return{
createBook: function(title, author, genre, pageCount, publisherID, ISBN){
/*Search whether to create before*/
var existingBook = existingBooks[ISBN];
if(existingBook){
return existingBook;
}else{
/* If not, create one and save */
var book = new Book(title, author, genre, pageCount, publisherID,ISBN);
existingBooks[ISBN] = book;
return book;
}
}
}
});
Manage external status
The external state is relatively simple. Except for the book we encapsulated, everything else needs to be managed here:
The code copy is as follows:
/*BookRecordManager Singleton for Borrowing Management*/
var BookRecordManager = (function(){
var bookRecordDatabase = {};
return{
/*Add a book borrowing record*/
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);
}
};
});
In this way, we have saved the same information of the same book in a bookmanager object and saved only one copy; compared with the previous code, we can find that it saves a lot of memory.
Enjoy the Yuan mode and DOM
I won’t say much about the DOM incident here. I believe everyone already knows it. Let’s give two examples.
Example 1: Centralized event management
For example, if we need to monitor its click event for many similar elements or structures (such as menus, or multiple lis in ul), then we need to bind events for each element. If there are very, very many elements, then the performance can be imagined. Combined with the knowledge of bubbles, if any child element is triggered, the event will bubble to the previous level element after the trigger is triggered. Therefore, using this feature, we can use the Encyclopedia mode, we can monitor event events on the parent elements of these similar elements, and then judge which child element has an event triggered, and then perform further operations.
Here we combine the bind/unbind method of jQuery to give an example.
HTML:
The code copy is as follows:
<div id="container">
<div href="#">More information (address)
<span>
Here is more information
</span></div>
<div href="#">More information (map)
<span>
<iframe src="http://www.map-generator.net/extmap.php?name=London&address=london%2C%20england&width=500...gt;"</iframe>
</span>
</div>
</div>
JavaScript:
The code copy is as follows:
stateManager = {
fly: function(){
var self = this;
$('#container').unbind().bind("click", function(e){
var target = $(e.originalTarget || e.srcElement);
// Determine which child element it is
if(target.is("div.toggle")){
self.handleClick(target);
}
});
},
handleClick: function(elem){
elem.find('span').toggle('slow');
}
});
Example 2: Applying Encyclopedia Mode to Improve Performance
Another example is still related to jQuery. Generally, we use element objects in the event callback function. We often use the form of $(this). In fact, it repeatedly creates a new object because this in the callback function is already the DOM element itself. We must use the following code:
The code copy is as follows:
$('div').bind('click', function(){
console.log('You clicked: ' + $(this).attr('id'));
});
// The above code should be avoided and avoid generating jQuery objects on the DOM element again, because you can directly use the DOM element itself.
$('div').bind('click', function(){
console.log('You clicked: ' + this.id);
});
In fact, if we have to use the form of $(this), we can also implement our own version of the single instance pattern, for example, we can implement a function like jQuery.signle(this) to return the DOM element itself:
The code copy is as follows:
jQuery.single = (function(o){
var collection = jQuery([1]);
return function(element) {
// Put elements in the collection
collection[0] = element;
// Return to the collection
return collection;
};
});
How to use:
The code copy is as follows:
$('div').bind('click', function(){
var html = jQuery.single(this).next().html();
console.log(html);
});
In this way, the DOM element itself is returned as it is, and the jQuery object is not created.
Summarize
The Flyweight mode is a mode that improves program efficiency and performance, which will greatly speed up the running speed of the program. There are many application scenarios: for example, if you want to read a series of strings from a database, many of these strings are repeated, then we can store these strings in the Flyweight pool (pool).
If an application uses a large number of objects, and these large numbers of objects cause great storage, you should consider using the Encyclopedia mode; and most states of objects can be external. If the external state of the object is deleted, many groups of objects can be replaced with relatively few shared objects. At this time, you can consider using Encyclopedia mode.