preface
Design pattern is for a specific problem in the process of object-oriented software design simple and elegant solution, each can solve the problem of a class of specific design patterns, this is very helpful programmers the ability to improve to solve the problem, so recently began to arrange design patterns related to arrange, this is the first article: the singleton pattern, then enter the singleton pattern
define
Singleton: The singleton ensures that a class has only one instance and that it instantiates itself and provides that instance to the entire system. Singleton is a creation pattern.
implementation
It is not complicated to implement a singleton pattern. The idea is to use a variable to indicate whether an object has been created for a class. If so, the next time an instance of the class is obtained, the previously created object is returned directly.
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
Copy the code
GetInstance () : getInstance (); getInstance () : getInstance (); getInstance (); getInstance ();
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
Copy the code
This example uses a self-executing function that returns the Singleton constructor. This implementation solves the problem of the elegant implementation of the previous example, but introduces new problems. Here the getName method is written inside the Singleton. Return a single instance and execute the getName business method. This is not an easy way to scale. If more business methods are added later, the Singleton function will become more and more bloated.
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
Copy the code
In this example, to separate fetching instance singletons from business methods, we introduce ProxySingleton, which is responsible for generating singletons, and the business method, which is responsible for separating the two responsibilities
application
The singleton pattern is widely used, such as thread pools, global caches, floating Windows, and so on. The following two scenarios are common
Global cache
Sometimes we want to cache some data in a session with a global variable, which is automatically cleared at the end of the session. In this case, we can use the singleton pattern to create a cache object, 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
}
Copy the code
In the above example, we define a Cache class to generate a singleton, Storage class for Storage, separation of responsibilities, so that you can Cache the desired data in a session
Floating window
In the page to process more friendly, we will always have various prompt pop-up window, where the need to display and then disappear, in fact we can create popup window is the same, using the singleton pattern, if the next generation, found that has been instances a popup window is returned directly, thus reducing costs, 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)
Copy the code
If you need to create a toast method later, create a new method called createToast. Then call getSingleton. Pass createToast to get an instance of toast
The advantages and disadvantages
Advantages:
- Controlled access to a unique instance is provided because the singleton class encapsulates its unique instance and therefore controls the form in which the instance is accessed
- Because there is only one object, it can save web resources and improve web performance
Disadvantages:
- The traditional singleton pattern is not conducive to extension, and the singleton class provides both instances and business methods, which violates the principle of single responsibility. However, the above example introduces that through a proxy class, the class that provides instances and business methods is separated, so that the responsibility can be single and conducive to extension
conclusion
This article is a summary of the singleton design pattern that we have seen recently, providing some simple examples and application scenarios, and hoping that you can understand the singleton pattern after reading it. If there is a mistake or not rigorous place, welcome criticism and correction, if you like, welcome to praise