Design pattern notes: single pattern

Keywords: Javascript Session

Preface

Design pattern is a simple and elegant solution to specific problems in the process of object-oriented software design. Each design pattern can solve a specific kind of problems, which is very helpful to improve the ability of programmers to solve problems. Therefore, recently, we began to sort out the design patterns. This is the first part: single pattern, and then we will enter the single pattern

Definition

Singleton mode: Singleton mode ensures that a class has only one instance, and it instantiates itself and provides the instance to the whole system. Singleton is a creation mode.

Realization

It's not complicated to implement a single instance mode. The implementation idea is to use a variable to mark whether an object has been created for a class. If it is, the object created before will be returned directly when the next instance of the class is obtained. For example:

let Singleton = function (name) {
  this.name = name
  this.instance = null
}
Singleton.prototype.getName = function () {
  return this.name
}
Singleton.getInstance = function (name) {
  if (!this.instance) {
    this.instance = new Singleton(name)
  }
  return this.instance
}
let a = Singleton.getInstance('a')
let b = Singleton.getInstance('b')
console.log(a === b) // true
console.log(a.getName()) // a
console.log(b.getName()) // a

Getting the unique instance of Singleton class through getInstance method is simple, but not elegant and direct. According to previous experience, getting the instance is through new Singleton(). Next, let's see more elegant implementation:

let Singleton = (function () {
  let instance = null
  let Singleton = function (name) {
    if (instance) {
      return instance
    }
    this.name = name
    return instance = this
  }
  Singleton.prototype.getName = function () {
    return this.name
  }
  return Singleton
})()
let a = new Singleton('a')
let b = new Singleton('b')
console.log(a === b) // true
console.log(a.getName()) // a
console.log(b.getName()) // a

This example uses a self executing function to return the constructor of Singleton. This implementation solves the problem of elegant implementation of the previous example, but brings new problems. Here, getName method is written inside Singleton, and Singleton function does two things: return a single instance and execute the getName business method. This writing method is not conducive to expansion. If you want to add more If there are multiple business methods, the Singleton function will become more and more bloated. Therefore, it is necessary to separate obtaining instances from business methods. For example:

let Singleton = function (name) {
  this.name = name
}
Singleton.prototype.getName = function () {
  return this.name
}

let ProxySingleton = (function () {
  let instance = null
  return function (name) {
    if (!instance) {
      instance = new Singleton(name)
    }
    return instance
  }
})()

let a = new ProxySingleton('a')
let b = new ProxySingleton('b')
console.log(a === b) // true
console.log(a.getName()) // a
console.log(b.getName()) // a

In this example, in order to separate obtaining instance Singleton from business method, proxy class ProxySingleton is introduced. ProxySingleton is responsible for generating Singleton, while business method is responsible for Singleton class, which separates the two responsibilities

application

Single instance mode is widely used, such as thread pool, global cache, floating window, etc. next, we will introduce two common scenarios

Global cache

Sometimes we want to cache some data in a session with a global variable, and clear it automatically when the session ends. At this time, we can consider creating a cache object by using the singleton mode, for example:

let Storage = function () {
  this.store = {}
}
Storage.prototype.setItem = function (key, value) {
  this.store[key] = value
}
Storage.prototype.getItem = function (key) {
  return this.store[key]
}
let Cache = (function () {
  let instance = null
  return function () {
    if (!instance) {
      instance = new Storage()
    }
    return instance
  }
})()

export {
  Cache
}

In the above example, a Cache class is defined to generate a single instance. The Storage class is used for Storage and separation of responsibilities, so that you can Cache the data you want in a session

Floating window

In order to make the program more friendly, we always have a variety of prompt pop ups, which are displayed in the required places and then disappear. In fact, we can create the same pop ups. Using the single instance mode, if we generate the next time, we can find that the instance has passed a pop-up window and then directly return, which can reduce the cost. For example:

let createLayer = function () {
  let div = document.createElement('div')
  div.innerHTML = 'Floating window'
  return div
}
let getSingleton = function (fn) {
  let result = null
  return function () {
    return result || (result = fn.apply(this, arguments))
  }
}
let createLayerSingleton = getSingleton(createLayer)
let layer = createLayerSingleton()
let layer1 = createLayerSingleton()
console.log(layer === layer1) // true
document.body.append(layer)

This example is also similar. It separates the method of creating a pop-up window from the method of obtaining an instance, which has a single responsibility and is conducive to extension. If you need to generate a toast method later, you need to add a createload method, and then call getSingleton again, and pass createload in to get an instance of a toast

Advantages and disadvantages

Advantage:

  • Provides controlled access to a unique instance, because a singleton class encapsulates its unique instance, so it can control the access form of the instance
  • Because there is only one object, it can save web resources and improve web performance

Disadvantages:

  • The traditional single instance mode is not conducive to extension. At the same time, the single instance class not only provides instances with business methods, but also violates the principle of single responsibility. However, the above example shows that through a proxy class, the classes that provide instances and business methods are separated, so that the responsibilities are single, which is conducive to extension

summary

This article is a summary of the recently seen singleton design patterns. It provides some simple examples and application scenarios. I hope you can understand the singleton design patterns after reading it.

If there is something wrong or not rigorous, please criticize and correct it. If you like it, please like it

Posted by ev5unleash on Sun, 24 Nov 2019 04:13:49 -0800