Article series

A singleton of javascript design patterns

Adapter pattern for javascript design pattern

Decorator pattern for javascript design pattern

Javascript design pattern proxy pattern

Comparison of javascript adaptation, proxy, and decorator patterns

Javascript design pattern state pattern

Iterator pattern for javascript design pattern

Javascript design pattern strategy pattern

Javascript design pattern observer pattern

Publish subscriber pattern for javascript design pattern

preface

In this paper, the code

concept

Singleton pattern: Ensures that a class has only one instance and provides a global access point to access it

You can see that the singleton pattern needs to satisfy two conditions

  • There’s only one instance
  • Global access

Model type

Implementation: Use a variable to store the class instance object (initial value null/undefined). During class instantiation, the system checks whether the class instance object exists. If it does, the system returns the instance. If it does not, the system returns after creating the class instance.

“Simple version” singleton pattern

class SingleObject {
    constructor(name) {
        this.name = name;
        this.instance = null
    }
    getName() {
        return this.name
    }
    static getInstance(name) {
        // Check whether an instance has been created
        if (!this.instance) {
            // If the unique instance does not exist, create it and store it
            this.instance = new SingleObject(name)
        }
        // If the unique instance already exists, it returns directly
        return this.instance
    }
}

const s1 = SingleObject.getInstance("Zhang")
const s2 = SingleObject.getInstance("Bill")
console.info(s1.getName()) / / zhang SAN
console.info(s2.getName()) / / zhang SAN
console.info(s1 == s2) // true

// We can only use getInstance to guarantee singletons. We can't guarantee singletons if we use new SingleObject
const s3 = new SingleObject("Fifty")
console.info(s3.getName()) / / Cathy
console.info(s3 == s2) // false
Copy the code

A static method getIntance is defined in the class to check whether an instance is created. If it is, the instance is directly returned; if not, the instance is created. Therefore, no matter how many times getIntance is called, the instance created for the first time is returned. Naturally, this referred to by s1.getName and s2.getName is s1

However, S3 is not created through getIntance but directly through new, so it is different from S1 and S2

Disadvantages:

  • This singleton pattern has two ways of creating instances, and is no longer singleton when new is used
  • The judgment of whether the instance has been instantiated (singleton judgment) and object creation are both handled by getIntance, which does not comply with the principle of single responsibility

Closure edition singleton pattern

const SingleObject = (function () {
    // An instance variable is defined inside the closure. Defining the instance variable outside of the closure pollens the global variable
    let instance = null
    return function (name) {
        // Check whether the variable is null
        if(! instance) {this.name = name
            instance = this
        }
        return instance
    }
})()
SingleObject.prototype.getName = function () {
    return this.name
}

const s1 = new SingleObject("Zhang")
const s2 = new SingleObject("Bill")
console.info(s1.getName()) / / zhang SAN
console.info(s2.getName()) / / zhang SAN
console.info(s1 == s2) // true

const s3 = new SingleObject("Fifty")
console.info(s3.getName()) / / zhang SAN
console.info(s3 == s2) // true
Copy the code

The singleton function is created by executing the function immediately, along with the closure, which is once again unified to create objects as new

Proxy edition singleton pattern

The simple version singleton pattern puts singleton management and object creation all in one class and does not conform to the single responsibility principle, whereas the proxy version serves to separate the two

class SingleObject {
    constructor(name) {
        this.name = name
    }
    getName() {
        return this.name
    }
}
const ProxySingleObject = (function () {
    let instance
    return function (name) {
        if(! instance) { instance =new SingleObject(name)
        }
        return instance
    }
})()

Copy the code

In this way, SingleObject is only responsible for the properties and methods associated with the class. The management of singletons is handled by ProxySingleObject and only exposed externally. You can work with modularity by exporting ProxySingleObject only, as shown in the code

Testing:

import ProxySingleObject from './ Proxy singleton pattern '
const s1 = new ProxySingleObject("Zhang")
const s2 = new ProxySingleObject("Bill")
console.info(s1.getName()) / / zhang SAN
console.info(s2.getName()) / / zhang SAN
console.info(s1 == s2) // true

const s3 = new ProxySingleObject("Fifty")
console.info(s3.getName()) / / zhang SAN
console.info(s3 == s2) // true
Copy the code

Lazy singleton pattern

The use of self-executing functions to create object instances while the code is executing is not appropriate, such as a pop-up login box, which may not require a login to access the home page.

We don’t need to create a popover when the page loads. We could have created it when we needed it

Lazy singleton pattern: Object instances are created only when needed.

Now let’s implement the login pop-up

<style>
    #modal {
        height: 200px;
        width: 200px;
        line-height: 200px;
        position: fixed;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
        border: 1px solid black;
        text-align: center;
    }
</style>

<body>
    <button id='login'>The login</button>
</body>
<script>
    var createLoginModal = (function () {
        let modal = null
        return function () {
            if(! modal) { modal =document.createElement('div')
                modal.innerHTML = "Login box"
                modal.id = "modal"
                modal.style.display = 'none'
                document.body.appendChild(modal)
            }
            return modal
        }
    })()
    document.getElementById("login").onclick = function () {
        var modal = createLoginModal()
        modal.style.display = 'block'
    }
</script>
Copy the code

Generic lazy singleton pattern

The above lazy singleton pattern also suffers from the integration of singleton control and creation, and is not general enough. What is universal? That is, the singleton control is separated into separate functions and the control is guaranteed to have only one object, something like this:

var obj 
if(! obj) { obj = xxx }Copy the code

Modify the code:

Encapsulate the logic of this operation into a getSingle function and pass in the function to be executed as an argument:

function getSingle(fn) {
	let result 
	return function() {
		result || (result = fn.apply(this,argumments))
	}
}
Copy the code

So the popover method we wrote above can be completely removed:

var createLoginModal = function () {
     var modal = document.createElement('div')
     modal.innerHTML = "Login box"
     modal.id = "modal"
     modal.style.display = 'none'
     document.body.appendChild(modal)
     return modal
}
var createSingleLoginModal = getSingle(createLoginModal)

document.getElementById('login').onclick = function() {
    var modal = createSingleLoginModal()
    modal.style.display = 'block'
}
Copy the code

Thus, any other singleton that needs to be implemented later, such as a shopping cart, can be called getSingleton(…) by passing in a function as an argument. Method to generate the corresponding instance object

Singleton usage scenarios

References to third-party libraries (multiple references will only use one library reference, such as jQuery)

// A simple example of how JQuery implements a single $
if(!window.Jquery){
    return window.Jquery()
}else{
    // Other code
}
Copy the code

Refer to the link

Core principles and application practice of JavaScript design pattern

conclusion

Your “like” is the biggest affirmation for me, if you feel helpful, please leave your appreciation, thank you!!