Peter Seibel, the author of "Practical Common Lisp", once said that if you need a pattern, there must be something wrong. The problem he refers to is that because of the inherent flaws of language, he has to find and summarize a universal solution.
Whether it is weakly typed or strongly typed, static or dynamic language, imperative or declarative language, every language has its inherent advantages and disadvantages. A Jamaican athlete has some advantages in sprinting and even boxing, but lacks in practicing yoga.
Warlock and Shadow Priest can easily become an excellent support, but an enemy Mage flying around the map with Macon on his back will be a little awkward. Switching to a program, it may take a lot of effort to implement decorators in static languages, but js can throw methods on objects at any time, so that the decorator pattern has become a standard in js. It's tasteless.
There are relatively few books about Javascript Design Pattern, "Pro javaScript Design" Patterns" is a relatively classic book, but the examples in it are quite lengthy, so I will summarize my understanding based on the codes I have written at work. If there is any deviation in my understanding, please feel free to correct me.
The definition of singleton mode is to generate the only instance of a class, but js itself is a "classless" "language. Many articles about js design patterns use {} as a singleton, which barely makes sense. Because there are many ways to generate objects in js, let's take a look at another more meaningful singleton.
There is such a common requirement. When a button is clicked, a mask layer needs to pop up on the page. For example, when you click to log in at web.qq.com.
#The code that generates the gray background mask layer is easy to write.
var createMask = function(){ return document,body.appendChild( document.createElement(p) ); } $( ‘button’ ).click( function(){ Var mask = createMask(); mask.show(); })
The problem is , this mask layer is globally unique, so every time createMask is called, a new p will be created. Although it can be removed when the mask layer is hidden, it is obviously unreasonable to do so.
Look again The second option is to create this p at the beginning of the page. Then use a variable to reference it.
var mask = document.body.appendChild( document.createElement( ”p’ ) ); $( ”button’ ).click( function(){ mask.show(); } )
In this way, only the page will be created A mask layer p, but another problem arises. Maybe we will never need this mask layer, which is a waste of p. Any operation on the dom node should be very stingy.
What if we can use a variable to determine whether p has been created?
var mask; var createMask = function(){ if ( mask ) return mask; else{ mask = document,body.appendChild( document.createElement(p) ); return mask; } }
Looks good, here we have indeed completed a function that generates a single column object. Let's take a closer look at what is wrong with this code.
First of all, this function has certain side effects. The reference to the external variable mask is changed within the function body. In a multi-person collaboration project, createMask is an unsafe function. On the other hand, the global variable mask is not It's not necessary. Let's improve it again.
var createMask = function(){ var mask; return function(){ return mask || ( mask = document.body.appendChild( document.createElement(‘p’) ) ) } }()
Use a simple closure to wrap the variable mask, at least for the createMask function, it is closed.
You may see this and feel that the singleton model is too simple. Indeed, some design patterns are very simple. Even if you have never paid attention to the concept of design patterns, you have used some designs in your daily code unknowingly. Patterns. Just like many years ago when I understood what the old man’s cart was, I also thought about it. It turns out that this is the old man’s cart. The 23 design patterns in GOF have also been used for a long time in software development. Patterns that exist and are used repeatedly. If the
programmerdoes not clearly realize that he has used certain patterns, then he may miss a more appropriate design next time (this passage is from "Yukihiro Matsumoto's Programming World" ).Back to the topic, the previous singleton still has shortcomings. It can only be used to create a mask layer. What if I need to write a function to create a unique xhr object? Can it be done? Find a general singleton wrapper.
Functions in js are of the first type, which means that functions can also be passed as parameters. Take a look at the final code.
var singleton = function( fn ){var result;return function(){return result || ( result = fn .apply( this, arguments ) );}} var createMask = singleton( function(){ return document.body.appendChild( document.createElement(‘p’) ); })
Use a variable to save the first A one-time return value, if it has been assigned, then the variable will be returned first in subsequent calls. The code that actually creates the mask layer is passed to the singleton wrapper through the
callback function. This method is actually called Bridge mode. About the bridge mode, I will talk about it a little later.However, the singleton function is not perfect, it still needs a variable result. Register the reference of p. Unfortunately, the functional characteristics of js are not enough to completely eliminate declarations and statements.
Related articles:
Detailed explanation of JavaScript design pattern classic strategy pattern
JavaScript design pattern classic simple factory pattern code example
##javascript design Detailed introduction to the observer pattern
The above is the detailed content of Detailed explanation of the classic JavaScript design pattern singleton pattern. For more information, please follow other related articles on the PHP Chinese website!