Open
Description
单例模式的定义是这样:
一个类只有一个实例,并提供一个访问该实例的全局节点。
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 对象,全局缓存等等。在业务开发中,当某个资源被频繁访问,产生不必要的请求浪费时,就可以考虑用单例模式来做缓存。