The singleton pattern

The singleton pattern is defined to ensure that a class has only one instance and provides a global access point to access it

1. Implement singleton pattern

It is not difficult to implement the singleton pattern, which simply uses a variable to indicate whether an instance of a class has already been created, and if so, the next time an instance of that class is fetched, the previously created object is returned. The code looks like this:

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

Singleton.prototype.getName = function () {
  console.log(this.name)
}

Singleton.getInstance = (function () {
  let instance = null
  return function (name) {
    if(! instance) { instance =new Singleton(name)
    }
    return instance
  }
})()
Copy the code

You can test if there is only one instance with the following test code:

var a = Singleton.getInstance('tom')
var b = Singleton.getInstance('jack')

console.log(a === b) // true
Copy the code
  • Although the top passesSingleton.getInstanceIn order to getSingletonClass, the implementation of the singleton pattern writing, but this singleton pattern code is not significant.
  • By increasing the “opacity” of this class, Singleton users must know that this is a Singleton class, as usualnew XXXThe way to get objects is different, but must be usedSingleton.getInstanceTo get the object.
  • Can still get throughnew XXXMethod to get an object.

2. Transparent singleton pattern

Our goal now is to implement a “transparent” singleton class from which users can create objects just like any other normal class with New XXX. The code is as follows:

var Singleton = (function () {
  var instance = null
  var Singleton = function (name) {
    if (instance) {
      return instance
    }
    this.name = name
    return (instance = this)}return Singleton
})()

var a = new Singleton('hh')
var b = new Singleton('kk')

console.log(a === b) // true
Copy the code

In this code, the Singleton constructor actually does two things:

  • Create an object
  • Ensure there is only one object

The problem is that one day you will need to create multiple instances of this class, so you will have to remove the section that controls the creation of unique objects

3. Implement singleton pattern with proxy

First look at the code:

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

Singleton.prototype.getName = function () {
  console.log(this.name)
}

var proxySingleton = (function () {
  var instance = null
  return function (name) {
    if(! instance) { instance =new Singleton(name)
    }
    return instance
  }
})()

var a = new proxySingleton('hh')
var b = new proxySingleton('kk')

console.log(a === b)
Copy the code

Instead of introducing a proxy class to implement the Singleton pattern, the logic responsible for managing the Singleton is moved into ProxySingleton, which becomes a generic class

This is also one of the applications of caching proxies

4. Lazy singleton

Lazy singletons are instances of objects that are created only when needed. Lazy singletons are the focus of the Singleton pattern, a very useful technique used in the first example, where the instance instance object is always created when singleton.getInstance is called

5. Interview questions

5.1. Implement a Storage

  • Description:

Realize Storage, so that the object as a singleton, based on localStorage encapsulation. SetItem (key,value) and getItem(key)

  • Ideas:

When dealing with singleton problems, first you need to know what getInstance and instance are used for, and then implement it. It doesn’t matter if you write judgment logic into static methods or constructors

  • Implementation:
class Storage {
  static getInstance() {
    if(! Storage.instance) { Storage.instance =new Storage()
    }
    return Storage.instance
  }

  getItem(key) {
    return localStorage.getItem(key)
  }
  setItem(key, value) {
    return localStorage.setItem(key, value)
  }
}

const storage1 = Storage.getInstance()
const storage2 = Storage.getInstance()

storage1.setItem('name'.'li lei')
/ / li lei
storage1.getItem('name')
// Also Li Lei
storage2.getItem('name')

/ / return true
storage1 === storage2
Copy the code