What is the singleton pattern
The Singleton Pattern ensures that a class has only one instance and provides a global access point to access it
Singleton is a relatively simple and easy to understand design pattern, but it is used in a wide range of scenarios, including Vuex also used singleton pattern.
This article introduces two implementations of the singleton pattern: classes and closures. It also introduces the singleton pattern in Vuex.
implementation
Class is a new syntax in ES6. Previously, we wanted to create an object instance by using the new constructor. Each time we call new, a new instance object is generated, completely independent of each other.
function Car (name) {
this.name = name;
}
var car1 = new Car('benz');
var car2 = new Car('audi');
console.log(car1 === car2) // false
Copy the code
So let’s think about, how do WE return the same instance object every time new?
There must be a variable that saves the instance object generated for the first time, and then when new is executed, it returns the instance object generated for the first time.
Let’s try this out in two ways: classes and closures.
Class implements
class SingletonCar {
constructor () {
this.name = 'benz';
}
static getInstance () {
if(! SingletonCar.instance) { SingletonCar.instance =new SingletonCar();
}
returnSingletonCar.instance; }}let car1 = SingletonCar.getInstance();
let car2 = SingletonCar.getInstance();
console.log(car1 === car2) // true
Copy the code
A class is the prototype of an instance, and all methods defined in a class are inherited by the instance. If you prefix a method with the static keyword, it means that the method is not inherited by the instance, but is called directly from the class. This is called a “static method”.
Static methods can call SingletonCar.getInstance() directly on the parent class rather than on the instance object. If a static method is called on an instance, an error is thrown indicating that the method does not exist.
To implement the singleton pattern with a class, just remember the getInstance() static method.
Closure implementation
var SingletonCar = (function () {
var instance;
var SingletonCarTemp = function () {
this.name = 'benz';
};
return function () {
if(! instance) { instance =new SingletonCarTemp();
}
return instance;
}
})();
var car1 = new SingletonCar();
var car2 = new SingletonCar();
console.log(car1 === car2) // true
Copy the code
With closures, instance variables are kept in memory, not garbage collected, used to hold unique instances, and only the first instance created is returned when new is called multiple times.
The singleton pattern in Vuex
Vuex is Vue’s state management library, similar to Redux and React. In fact, Vuex’s concept comes from Flux architecture. It uses a global Store to Store all application states, and then provides some apis for users to read and modify. Once you see a globally unique Store, you can think of a singleton pattern.
How to reference Vuex
import Vue from 'vue'
import Vuex form 'vuex'
import store from './store'
Vue.use(Vuex)
new Vue({
el: '#app',
store
})
Copy the code
Vuex is a plug-in that can be installed by calling vue.use (). For details on how to write the Vue plug-in, please refer to the official documentation
Vuex internally implements a install method that is called when vue.use (), and Vue is passed in as an argument to the Install method to inject Store into Vue. But if you’ve tried calling vue.use (Vuex) multiple times in your development environment, you know that the browser will give you an error. Let’s take a look at the internal implementation of Vuex.
How does Vuex guarantee a unique Store
Vuex source code:
let Vue ... Export function install (_Vue) {// Check whether vue. use(Vuex) has been executed. If (Vue &&_vue === Vue) {if (process.env.node_env! == 'production') { console.error( '[vuex] already installed. Vue.use(Vuex) should be called only once.' ) } return } // If vue.use (Vuex) is executed for the first time, assign the passed _Vue to the defined variable Vue Vue = _Vue // Vuex initialization logic applyMixin(Vue)}Copy the code
The full source code can be found at [vuex/ SRC /store.js](github.com/vuejs/vuex/…
We can see that inside Vuex, we first define a variable Vue, notice that this is not a real Vue, just a variable, also called Vue.
When vue. use(Vuex) is invoked, the install method is called, and the actual Vue is passed in as an argument. If vue. use(Vuex) is executed multiple times, applyMixin(Vue) is executed only once. So there is only one unique Store, which is the implementation of the singleton pattern in Vuex.
practice
Implement a globally unique Loading mask.
Train of thought
In the process of business development, there are many requirements in Loading state. In this case, we can directly take out the singleton mode and remember the getInstance static method or the closure instance variable.
The complete code
<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, Initial-scale =1.0"> <meta http-equiv=" x-UA-compatible "content="ie=edge"> <title> Loading</title> <style>.loading { width: 100vw; height: 100vh; line-height: 100vh; position: absolute; top: 0; left: 0; background-color: #000; opacity: .7; color: #fff; text-align: center; } </style> </head> <body> <button id="startLoading"> </button> <script> const Loading = (function () {let instance return function () { if (! Instance) {instance = document.createElement('div') instance.innerhtml = 'Loading... ' instance.id = 'loading' instance.className = 'loading' document.body.appendChild(instance) } return instance } })() document.getElementById('startLoading').addEventListener('click', () => { const loading = new Loading() }) </script> </body> </html>Copy the code
conclusion
The singleton pattern, which ensures that there is only one instance of a class, is implemented using the getInstance static method, or the instance variable if implemented using a closure. When we encounter a globally unique state like Vuex in business development, that is when the singleton pattern comes into play.