原来单例模式无处不在|小册免费学

前言

如今大部分前端开发,估计只学了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如何引入项目使用?

  1. 创建store文件夹,并新建index.js文件
import Vue from 'vue'
import Vuex from 'vuex'
// 安装vuex插件
Vue.use(Vuex);

export default new Vuex.Store({
    state,
    actions,
    mutations,
    getters
})
复制代码
  1. 再将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对象,在复杂的业务场景实现数据共享。

三、总结

单例模式,是设计模式中最简单的模式,应用场景也相当广泛。我们就从由易到难,慢慢展开学习设计模式吧~~

本文正在参与「掘金小册免费学啦!」活动, 点击查看活动详情

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享