持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第12天,点击查看活动详情
定义
单例模式(Singleton Pattern):又被称为单体模式,是只允许实例化一次的对象类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,
好处
- 在程序中多次使用同一个对象且作用相同时,为了防止频繁的创建对象和销毁使得内存飙升,单例模式可以让程序仅在内存中创建一个对象,让所有需要调用的地方都共享这一单例对象。
实现
单例就是保证一个类只有一个实例,实现的方法一般是先判断实例存在与否,如果存在直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。在JavaScript里,单例作为一个命名空间提供者,从全局命名空间里提供一个唯一的访问点来访问该对象。
对象字面量
全局对象就是最简单的单例模式。 如下:
var mySingleton = {
property: 'xman',
method: function () {
console.log('hello');
}
}
以上就是使用对象字面量的方法创建了单例对象mySingleton, 但是缺点也很明显:
- 没有封装性,所有的属性方法都暴露出来;
- 全局变量容易造成命名空间污染;
- 对象一开始就创建,可能会用不上
下面我们来一步步的完善下。
第一步: 进行封装
我们需要添加一些私有属性和方法,然后通过闭包在内部封装这些变量和函数声明。 如下:
var mySingleton = function () {
// 声明私有属性和方法
var privateVariable = 'private variable';
function privateMethod () {
console.log(privateVariable);
}
// 返回公用变量和方法
return {
publicMethod: function () {
privateMethod();
},
publicVariable: 'public variable'
}
}
var singleton = Singleton();
singleton.publicMethod(); // 输出 'private variable'
console.log(singleton.publicVariable); // 输出 'public variable'
ES6实现
利用ES6 中的class关键字和static关键字,其中static关键字是用来修静态方法的。
class Singleton {
contructor (variable) {
this.variable = variable;
this.instance = null;
}
// 提供一个静态的方法来获取对象实例
static getInstance (variable) {
if (!this.instance) {
this.instance = new Singleton(variable);
}
return this.instance;
}
}
测试:
let instance1 = Singleton.getInstance('test');
let instance2 = Singleton.getInstance('test');
instance1 === instance2; // true 是同一个实例
第二步: 延迟创建
就是在使用的时候才初始化,该如何处理?
var Singleton = (function() {
// 单例实例引用
var instance = null;
function init() {
return {
publicMethod: function () {
console.log('hello');
},
publicVariable: 'public variable'
}
}
return {
getInstance: function () {
// 先判断,存在直接返回,如果不存在就创建
if(!instance) {
instance = init();
}
return instance;
}
}
})();
// 使用时调用公用的方法来获取实例
Singleton.getInstance().publicMethod(); // 输出 'hello'
代码中使用自执行匿名函数返回真正的单例类的构造方法
以上代码就是所谓延迟创建的形式,也被称为‘惰性创建’。
通用的惰性单例
完善一个通用的惰性单例
可以将管理的逻辑从原来的代码中抽离出来,封装在getSingle函数内部,创建对象的方法fn被当做参数动态传入getSingle函数:
var getSingle = function (fn) {
var result;
return result || (result = fn.apply(this, arguments));
}
以下是创建唯一的iframe用于动态加载第三方页面:
var createSingleIframe = getSingle( function () {
var iframe = document.createElement('iframe');
document.body.appendChild( iframe );
return iframe;
})
常见应用实例
登录框
点击登录按钮,只会弹出有且仅有一个登录框,即使后面再点击登录按钮,也不会再弹出多一个弹框。这就是单例模式的典型应用。
vuex中的store
-
Vuex3.x版本 在
Vuex3.x版本中是通过Vue.use(Vuex)安装Vuex插件,而Vuex插件是一个对象,它在内部实现了一个install方法,这个方法会在插件安装时被调用,从而把Store注入到Vue实例里去。也就是说每install一次,都会尝试给Vue实例注入一个Store。 -
VueX4版本
vuex - createStore 代码如下:
export function createStore (options) {
return new Store(options)
}