Singleton pattern
Ensure that a class has only one instance and provide a global access point to access it.
Singleton pattern is a common pattern. We often need only one object, such as thread pool, global cache, window object in browser and so on.
Singleton pattern in JavaScript
1. Use namespaces
There are many ways to implement singletons in JavaScript. The simplest way is to use object literals, which can contain a lot of attributes and methods.
let people = { name: "Jack", age: 18, play() { console.log('i like game'); } }
You can also create namespaces dynamically
// Define objects var MyApp = {}; // Object Method MyApp.namespace = function( name ){ // Partition of parameters into arrays var parts = name.split( '.' ); // Define variables var current = MyApp; // Create attributes within objects for ( var i in parts ){ if ( !current[ parts[ i ] ] ){ current[ parts[ i ] ] = {}; } current = current[ parts[ i ] ]; } }; MyApp.namespace( 'event' ); MyApp.namespace( 'dom.style' ); /******************* It doesn't matter if you don't understand the above ***********************************************************/ // The above code is equivalent to var MyApp = { event: {}, dom: { style: {} } };
2. Encapsulating private variables with closures
var user = (function(){ var __name = 'sven', __age = 29; return { getUserInfo: function(){ return __name + '-' + __age; } } })();
We use underscores to specify private variables _name and _age, which are encapsulated in the scope of closure generation and cannot be accessed externally, thus avoiding global command contamination.
Implementing a standard singleton pattern
var Singleton = function( name ){ this.name = name; this.instance = null; }; Singleton.prototype.getName = function(){ alert ( this.name ); }; Singleton.getInstance = function( name ){ if ( !this.instance ){ this.instance = new Singleton( name ); } return this.instance; }; var a = Singleton.getInstance( 'sven1' ); var b = Singleton.getInstance( 'sven2' ); alert ( a === b ); // true
We use Singleton.getInstance to get the only object of the Singleton class. This method is relatively simple, but there is a problem, which is to increase the "opacity" of this class. Users of the Singleton class must know that this is a singleton class, which is different from the previous way to get objects through new XXX. Singleton.getInstance is used to get the object.
Transparent singleton mode
var CreateDiv = (function(){ var instance; var CreateDiv = function( html ){ if ( instance ){ return instance; } this.html = html; this.init(); return instance = this; }; CreateDiv.prototype.init = function(){ var div = document.createElement( 'div' ); div.innerHTML = this.html; document.body.appendChild( div ); }; return CreateDiv; })(); var a = new CreateDiv( 'sven1' ); var b = new CreateDiv( 'sven2' ); alert ( a === b ); // true
To encapsulate instance, we use self-executing anonymous functions and closures, and let the anonymous function return
A true Singleton constructor, which adds complexity to some programs
3. Implementing the singleton pattern with proxy
var CreateDiv = function( html ){ this.html = html; this.init(); }; CreateDiv.prototype.init = function(){ var div = document.createElement( 'div' ); div.innerHTML = this.html; document.body.appendChild( div ); }; // proxySingletonCreateDiv: var ProxySingletonCreateDiv = (function(){ var instance; return function( html ){ if ( !instance ){ instance = new CreateDiv( html ); } return instance; } })(); var a = new ProxySingletonCreateDiv( 'sven1' ); var b = new ProxySingletonCreateDiv( 'sven2' ); alert ( a === b );
By introducing proxy classes, we have also completed the writing of a single case pattern. Unlike before, now we have
Move the logic responsible for managing the singletons to the proxySingleton CreateDiv proxy class. In this way, CreateDiv becomes a common class, which can be combined with proxy Singleton CreateDiv to achieve the effect of the singleton pattern.
Inert singleton
Lazy singletons refer to creating object instances when needed.
var Singleton = (function () { var instantiated; function init() { /*Here we define the singleton code*/ return { publicMethod: function () { console.log('hello world'); }, publicProperty: 'test' }; } return { getInstance: function () { if (!instantiated) { instantiated = init(); } return instantiated; } }; })(); /*Call public methods to get instances:*/ Singleton.getInstance().publicMethod();
Through the above methods, we can achieve the purpose of saving resources by initializing only when used.
At present, there are so many understandings about the singleton pattern that new understandings will continue to be updated and slipped away (~)