Skip to content

单例模式 #59

Open
Open
@myLightLin

Description

@myLightLin

单例模式的定义是这样:

一个类只有一个实例,并提供一个访问该实例的全局节点。

JS 并不像传统面向对象语言 Java 那样,我们可以使用闭包来模拟实现单例模式:

var Singleton = (function() {
  var instance
  return function () {
    if (!instance) {
      instance = new Object()
    }
    return instance
  }
})()

var obj1 = new Singleton()
var obj2 = new Singleton()
console.log(obj1 === obj2)  // true

单例模式的思想非常简单:用一个变量存储实例,当获取实例时,如果有就直接返回;没有就创建实例并返回。那么对应到平时的业务场景中,有哪些地方可以应用单例呢?

应用场景

在开发小程序时,遇到过这样一个需求:

有两个弹窗组件 A 和 B,它们依赖一份共用数据。这份数据存储在亚麻的 s3 上,是一份不常更新的公共配置数据。一开始只有组件 A 的时候,我们在组件内直接 io 请求这份数据就行;但是现在多了组件 B,B 组件内也需要拿这份数据,显然我们不可能在页面挂载时,两个组件同时发出两个相同请求去拿这份数据。于是就需要把获取数据的逻辑提取出来,对请求进行缓存,在整个小程序生命周期内只执行一次,这样不管有多少个组件同时去请求这份数据,实际只会发出一个请求。

这个过程就用到了单例模式,大致代码是这样子的:

// utils.js
let cacheRequestPromise = null
export function getData() {
  if (cacheRequestPromise) {
    return cacheRequestPromise.then(processData)  // processData 函数用于处理 res 响应数据
  }
  cacheRequestPromise = wx.request({
     url: '',
     success: function(res) {
       processData(res)
     },
     fail: function() {
       cacheRequestPromise = null
     }
  })
  
  return cacheRequestPromise
}

用一个 cacheRequestPromise 变量来缓存请求,保证整个过程中请求实例只有一个,这样就避免了多次相同请求,这其中其实就应用了单例模式的思想。

总结

单例模式的特点就是保证全局只有一个实例,实例只被初始化一次。它比较适合控制对共享资源的访问。例如数据库连接池,全局 window 对象,全局缓存等等。在业务开发中,当某个资源被频繁访问,产生不必要的请求浪费时,就可以考虑用单例模式来做缓存。

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions