前言
如今大部分前端开发,估计只学了html、css、JavaScript基础知识,就直接上手写代码,然后又使用各种各样的框架(Vue/React/Angular)不停地做项目,未曾静下心来看看设计模式之类的书籍,深入理解其编程的精髓,找到“多变”技术框架/库背后“不变”的东西。我也是这大部分之一,曾经面试大厂高级岗位多次以失败告终,其主要原因就是设计思维、算法基础经不起面试官的推敲检验。总结失败教训后,我决心从“JavaScript设计模式”开始好好学习,重塑自己的编码设计思维,提升自己如下专业能力:
- 能用健壮的代码去解决具体的问题
- 能用抽象的思维去应对复杂的系统
- 能用工程化的思想去规划更大规模的业务
一、单例模式的概念
单例模式的定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
出自《JavaScript设计模式与开发实践》的官方定义。
单例模式是设计模式中相对较为容易理解、容易上手的一种模式。结合我们JavaScript来看,很多场景都属于单例模式。比如,当我们单击登录按钮的时候,页面中会出现一个登录浮窗,而这个登录浮窗是唯一的,无论单击多少次登录按钮,这个浮窗都只会被创建一次,那么这个登录浮窗就适合用单例模式来创建。单例模式的应用场景涉及较广,比如还有vuex、storage、公共组件库等。
二、单例模式的实现
2.1 单例模式的实现思路
我们先不考虑单例模式的使用场景,先来试着手写实现一个单例模式。从定义来看,单例模式关键特征是一个类只有一个实例,多次创建实例都是唯一的。
那么实现思路是:用一个变量来标志当前是否已经为某个类创建过对象,如果创建过,则下一次获取该类的实例时,直接返回之前创建的对象。代码实现如下:
var SingleDog = function(){}
SingleDog.getInstance = (function() {
// 定义自由变量instance,模拟私有变量
let instance = null
return function() {
// 判断自由变量是否为null
if(!instance) {
// 如果为null则new出唯一实例
instance = new SingleDog()
}
return instance
}
})()
const s1 = SingleDog.getInstance()
const s2 = SingleDog.getInstance()
console.log(s1 == s2)// true
复制代码
上述getInstance的逻辑,是采用JavaScript的闭包来实现的,不管调用多少次,SingleDog都只会返回同一个实例。所以生成的实例s1、s2都指向了同一个引用地址,即唯一的实例。
2.2 结合vuex来加深理解单例模式
近年来,vuex、redux等状态管理工具层出不穷。其实他们内部都是通过实现一个全局的Store来存储应用所有数据状态。Store的实现,正是应用了单例模式。我们以vuex为例,一起研究看看Store内部的实现。
vuex如何引入项目使用?
- 创建store文件夹,并新建index.js文件
import Vue from 'vue'
import Vuex from 'vuex'
// 安装vuex插件
Vue.use(Vuex);
export default new Vuex.Store({
state,
actions,
mutations,
getters
})
复制代码
- 再将store/index.js引入vue项目入口文件main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store/index'
// 将store注入到Vue实例中
new Vue({
el: '#app',
router,
store,
render: h => h(App)
});
复制代码
上述代码中调用Vue.use()
方法,进行安装vuex插件,实质会调用到其install
方法。我们打开vuex源码,找到install
方法的实现:
function install (_Vue) {
// 判断传入的Vue实例对象是否已经被install过Vuex插件
if (Vue && _Vue === Vue) {
{
console.error(
'[vuex] already installed. Vue.use(Vuex) should be called only once.'
);
}
return
}
// 若没有,则为这个Vue实例对象install一个唯一的Vuex
Vue = _Vue;
// 将Vuex的初始化逻辑写进Vue的钩子函数里
applyMixin(Vue);
}
复制代码
上述vuex源码实现便是单例模式,通过判断安装过vuex插件的Vue实例是否存在,存在就直接返回,这套路似乎和getInstance
如出一辙。这样的实现方式,可以保证创建的Vue实例只会被install一次vuex插件,每个Vue实例便只会拥有一个全局的Store对象,在复杂的业务场景实现数据共享。
三、总结
单例模式,是设计模式中最简单的模式,应用场景也相当广泛。我们就从由易到难,慢慢展开学习设计模式吧~~
本文正在参与「掘金小册免费学啦!」活动, 点击查看活动详情