“This is the seventh day of my participation in the August More Text Challenge. For details, see: August More Text Challenge.”

preface

At the top end of the interview, often encounter some questions about design patterns, each time the answer is not ideal. Coincides with the more challenging activities in August, I am prepared to spend a month to get a good understanding of design patterns, so as to increase my confidence for the interview.

The six principles of design patterns have been described in detail in previous articles:

  • “Interview confidence” — The single Responsibility principle of design mode | more challenging in August
  • “The confidence of interview” — the open and Closed principle of design mode | more challenging in August
  • “Interview confidence” — the least knowledge principles of design patterns | more challenging in August
  • “The Strength of interview” — The Richter’s Principle of substitution in Design mode | more challenging in August
  • “The Strength of the interview” — The Design pattern relies on the Inversion principle | more challenging in August
  • “The strength of interview” – Interface Isolation principles in design patterns | more challenging in August

Next, let’s study and practice the singletons of the design pattern, strictly following the six principles. If you are not familiar with the six principles, please visit the link above.

define

The singleton pattern ensures that a class has only one instance and provides a global point of access to it.

Your own understanding

Usually we can have a global variable that makes one object accessible, but it doesn’t prevent instantiating multiple objects. One of the best ways to do this is to make the class itself responsible for keeping a unique instance of it, and the class ensures that no other instance can be created, and that it provides a method to access that instance.

Implement the singleton pattern

Implementing a simple singleton pattern is nothing more than using a variable to cache the object generated by a class instantiation, and then using that variable to determine whether a class has been instantiated. If a variable has a value, the next time you want to get an object generated by an instantiation of that class, you return the variable directly (the object generated by the previous instantiation).

var Singleton = function(name) { this.name = name; this.instance = null; }; Singleton.prototype.init = function() { //... Initialize}; Singleton.getInstance = function(name) { if (! this.instance) { this.instance = new Singleton(name); this.instance.init(); } return this.instance; }; var a = Singleton.getInstance('a'); var b = Singleton.getInstance('b'); console.log(a === b); // trueCopy the code

Im normally every time a class instance into the object is different, in the code above using Singleton. GetInstance access to the Singleton class instances are assigned, im into object and the object a and object b, perform the console, log (a = = = b) print out the true, The above code succeeds in implementing the singleton pattern.

Or do not mount the instantiated object to the property of the class, as follows:

var Sington = function( name ){ this.name = name; }; Singleton.prototype.init = function() { //... Initialize}; Singleton.getInstance = (function(){ var instance = null; return function( name ){ if ( ! instance ){ instance = new Singleton( name ); instance.init(); } return instance; }}) ();Copy the code

The instance variable is used to cache the object generated by class instantiation. We create a closure with a self-executing anonymous function. We store the instance variable in the closure and use it to determine whether the Singleton class has been instantiated every time we execute Singleton.

Transparent singleton pattern

A problem with the above method of implementing the Singleton pattern is that it adds “opacity” to the class. Users of the Singleton class must know that it is a Singleton class. Instead of instantiating the class in a new XXX way, use Singleton. Therefore, there is a different way to implement the transparent singleton pattern.

const Singleton = (function() { let instance; const Singleton = function(name) { if (instance) { return instance; } this.name = name; this.init(); return instance = this; }; Singleton.prototype.init = function() { //... Initialize}; return Singleton; }) (); const a = new Singleton('a'); const b = new Singleton('b'); console.log(a === b); // trueCopy the code

In the above code, the Constructor of the Singleton class is a self-executing anonymous function that forms a closure that caches the instance variable that determines whether the class has been instantiated and the object generated by the class instantiation, and returns the real Constructor of the Singleton class. You can then use New Singleton to instantiate the Singleton class.

The principles of design patterns must be followed

The above code is not perfect for two things:

  • It’s a bit odd to have the real constructor of the Singleton class return in a self-executing anonymous function.

  • The constructor of the Singleton class violates the single responsibility principle of the design pattern by doing two things: creating the object generated by the class instantiation and executing the init method, ensuring that it can only be instantiated once.

Implementing any design pattern follows the principles of the design pattern by separating the responsibilities of creating objects generated by class instantiation and performing initialization init methods from the responsibilities of ensuring that you can only instantiate them once. The following uses a proxy to implement the singleton pattern.

const Singleton = function (name) { this.name = name; this.init(); } Singleton.prototype.init = function () { //... Initialize}; const PropxSingleton = (function () { var instance; return function (name) { if (! instance) { instance = new Singleton(name); } return instance; }}) (); var a = new PropxSingleton('a'); var b = new PropxSingleton('b'); console.log(a === b); //trueCopy the code

The above implements the Singleton pattern for the Singleton class with the proxy class propxSingleton, while the Singleton class is still a generic class and does not affect its use elsewhere.

However, the above code is not perfect. If you want to implement the singleton pattern for another class, you have to modify the code for the agent class propxSingleton. It does not conform to the open-close principle of the design pattern, and you have to encapsulates a getPropxSingleton method that gets the agent class propxSingleton of a different class.

const Singleton = function (name) { this.name = name; this.init(); } Singleton.prototype.init = function () { //... Initialize}; const getPropxSingleton = function (customClass) { return (function () { var instance; return function (name) { if (! instance) { instance = new customClass(name); } return instance; ()}}}); const PropxSingleton = getPropxSingleton(Singleton); var a = new PropxSingleton('a'); var b = new PropxSingleton('b'); console.log(a === b); //trueCopy the code

Use ES6 to implement a singleton pattern

These are all singletons implemented in ES5, now they are all implemented in ES6, so use ES6 to implement a singleton pattern.

class Singleton { constructor(name) { this.name = name; this.init(); } init() { //... Const getPropxSingleton = function (customClass) {let instance = null; return class { constructor() { if (instance) return instance; return instance = new customClass(... arguments) } } }; const PropxSingleton = getPropxSingleton(Singleton); var a = new PropxSingleton('a'); var b = new PropxSingleton('b'); console.log(a === b); //trueCopy the code