preface

What should be your first impression of a design pattern

In the course of the development of JavaScript, the pioneers have summed up many solutions to specific problems from practice. Simply put, a design pattern is a concise and elegant solution to a given problem in a given situation

Over the next few days, I’ll document various common design patterns in JavaScript. Maybe you’re already familiar with it, maybe you use it on a regular basis, but you’re not familiar with the concept, or maybe you just have a vague idea about it. Then, I believe that this series will bring you some harvest

By default, you have at least mastered these common patterns

  • this 
  • closure
  • Higher-order functions
  • Prototype and prototype chain


If there are mistakes in the article, please also see friends more advice, thanks in advance

Let’s start with the singleton pattern

concept

As the name implies, there is only one instance

Definition: Ensuring that a class has only one instance and provides a global access point to access it, does the concept of global variables spring to mind? Global variables are undeniably consistent with the concept of the singleton pattern. However, we generally do not and should not use it as a singleton for two reasons:

  • Global naming pollution
  • Not easy to maintain, easy to override

Before ES6, we used to simulate a class using a constructor. Now we can create a class directly using the class keyword, even though it is essentially a prototype

To ensure that there is only one instance of a class, we need to provide a variable to indicate whether an instance of a class has already been created. So the core of the singleton pattern is to ensure that there is only one instance and provide global access

Around this core, we also have a basic understanding of the singleton pattern implementation mode implementation base version According to the singleton pattern definition, we can use the following simple implementation

implementation

Basic version

According to the definition of the singleton pattern, we can simply implement it in the following way

var Singleton = function(name){this.name = name} singleton. instance = null // Initialize a variable singleton. getInstance =function(name) {// Determine if the variable has been assigned, if not, make it an instantiated object of the constructorif(! this.instance) { this.instance = new Singleton(name) }return this.instance
}

var a = Singleton.getInstance('Tadpole')
var b = Singleton.getInstance('Amy')

a === b // trueCopy the code

The above code clearly reflects the definition of the singleton pattern. Only one instance is initialized by way of an intermediate variable, so a and B are exactly equal in the end

We can also use the ES6 class keyword to do this

Class Singleton {constructor(name){this.name = name this.instance = null} class Singleton {constructor(name){this.name = name this.instance = null}if(! this.instance) { this.instance = new Singleton(name) }return this.instance
    }
}Copy the code

It’s not hard to see how ES6 is implemented in the same way that we implemented it through constructors

Problem: not transparent enough, we need to restrict how class instantiations are called

The coupling of functional business code together is not conducive to later maintenance of the constructor. Let’s make a simple change to the above approach

// Attach the variable directly to the constructor and return itfunction Singleton(name) {
    if(typeof Singleton.instance === 'object') {
        returnSingleton.instance} // Create instance this.name = namereturn Singleton.instance = this
}

var a = new Singleton('Tadpole')
var b = new Singleton('Amy')Copy the code

The new keyword can be used to initialize instances, but at the same time, there are new problems

  • Judging the Single. Instance type to return, you may not get the expected result
  • The coupling is too high

Class Singleton {constructor(name) {this.name = nameif(! Singleton.instance) { Singleton.instance = this }return Singleton.instance
    }
}Copy the code

closure

By defining the singleton pattern, you want to ensure that there is only one instance and that global access is available. Closures, then, can certainly do the same

var Singleton = (function () {
    var SingleClass = function () {}; 
    var instance; 
    return function () {
        if(! Instance) {instance = new SingleClass() // New SingleClass()}return instance;
    }
})()Copy the code

By virtue of closures, a variable is saved and eventually returned, providing global access

Again, the above code does not solve the coupling problem

Let’s take a closer look at this piece of code and see if we can achieve a separation of functionality if we pull out the constructor part of it

The proxy implementation

Modify the above code

function Singleton(name) {
    this.name = name
}

var proxySingle = (function(){
    var instance
    return function(name) {
        if(! instance) { instance = new Singleton(name) }return instance
    }
})()Copy the code

Take the steps to create functions out of the functions, and move the logic responsible for managing singletons into proxySingle. The purpose of this is to turn the Singleton class into a normal class in which we can write some business logic separately, thus achieving the effect of logic separation

We have now achieved the effect of logical separation and opacity. But does the class responsible for the proxy already meet our requirements? The answer is no. Imagine if our constructor had more than one argument, and we should have represented it in the proxy class

So, is there a more general way to do it

Generic lazy singleton

In the last few rounds, we’ve pretty much finished creating the singleton pattern. Now we need to find a more general way to solve the problems left behind

Imagine if we had a function as an argument

// Pass the function as an argument var Singleton =function(fn) {
    var instance
    return function() {// Collect parameters using apply and return the result by executing the parameters passed inreturn instance || (instance = fn.apply(this, arguments))
    }
}Copy the code

The biggest advantage of this approach is that we cache the results we want and only call them when we need them, fulfilling the single responsibility of encapsulation

application

As mentioned earlier, all patterns are derived from practice, so let’s take a look at how they are used in real development

From the definition of the singleton pattern, it is not difficult to think of its practical use in development, such as: global mask layer

A global mask layer cannot be created every time it is called. The best way to create it is to create it only once, save it with a variable, and return the result when called again

// Create a mask layerfunction () {
    var div = document.createElement('div')
    div.style.width = '100vw'
    div.style.height = '100vh'
    div.style.backgroundColor = 'red'
    document.body.appendChild(div)
    returnVar createSingleLayer = Singleton(createDiv) document.getelementById ('btn').onclick = functionVar divLayer = createSingleLayer()}Copy the code

Of course, there are many scenarios that are applicable in practice, such as login boxes and state management tools like Vux that we might use, which actually fit the singleton pattern

Afterword.

The singleton pattern is a simple and practical pattern, and we can create many practical and elegant applications by creating objects and managing singleton. Of course, it also has its own disadvantages, such as only one instance ~

Only when it is properly used can it bring out its maximum power

communication



Like this article, trouble like, favorites, forward, in the process of learning the web front end, often because there is no information or no one to guide their own do not want to learn, so I specially prepared a group 545667817, supporting information can find management sister to receive! No matter which stage of learning partners can obtain their own corresponding information, like the collection into the group partners have the opportunity to obtain the entity web front-end learning books, thank you for your support!!