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!!