一、介绍
定义:
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
主要解决:
一个全局使用的类频繁地创建与销毁。
如何解决:
判断系统是否已经有这个单例,如果有则返回,如果没有则创建。
应用实例:
Vuex,Redux,ES6中的export等
使用场景:
- 仅需创建一次实例,在
vue中的use方法中,如果已经安装一次插件之后,将不再安装。
优点:
- 只创建一个实例,避免多次创建销毁导致的性能消耗和内存消耗。
- 对于全局状态管理来说,避免多次创建导致数据混乱,不可追踪。
缺点:
二、代码实现
1.基本实现
利用ES6语法,通过new类创建一个实例。
把要返回的单例定义成类的静态属性
class BangBangTang {
static instance = undefined
constructor(type) {
if (BangBangTang.instance) {
return BangBangTang.instance
} else {
this.type = type
BangBangTang.instance = this
}
}
}
const tang = new BangBangTang('超级棒棒糖')
const tang_ = new BangBangTang('棒棒糖')
console.log(tang)
console.log(BangBangTang.instance)
把要返回的单例隐藏在闭包里
const BangBangTang = (function () {
let instance = undefined
return class {
constructor(data) {
if (!instance) {
this.name = data.name
instance = this
} else {
return instance
}
}
}
})()
const tang = new BangBangTang({ name: "超级棒棒糖" })
const tang_ = new BangBangTang({ name: "棒棒糖" })
console.log("tang:", tang, "tang_:", tang_,)
console.log(tang === tang_) //true
2.拓展:需要给多个类添加单例模式
遵守单一职责原则:把创建对象和保证只有一个对象两个功能分开
需求:需要给多个类添加单例模式,减少重复判断单例的代码
通过代理模式
class BangBangTang {
constructor(data) {
this.name = data.name;
}
}
class Toy {
constructor(data) {
this.name = data.name;
}
}
//代理模式
const proxySingletonCreate = function (fn) {
let instance = undefined;
return function (data) {
if (!instance) {
instance = new fn(data);
}
return instance;
};
};
const SingletonToy = proxySingletonCreate(Toy);
const SingletonTang = proxySingletonCreate(BangBangTang);
const toy = new SingletonToy({ name: "小火车" });
const toy_ = new SingletonToy({ name: "小火车" });
console.log("toy:", toy, "toy_:", toy_);
console.log(toy === toy_); //true
const tang = new SingletonTang({ name: "超级棒棒糖" });
const tang_ = new SingletonTang({ name: "棒棒糖" });
console.log("tang:", tang, "tang_:", tang_);
console.log(tang === tang_); //true
三、惰性单例
概念:在需要的时候才创建对象实例
四、JavaScript中的单例模式
JavaScript是基于原型的面向对象,也是动态语言类型。可以直接创建一个对象,而不需要通过类来创建对象。
所以,可以省去创建类的代码,而直接生成对象。
const proxySingletonCreate = function () {
let instance = undefined;
return function (data) {
if (!instance) {
instance = data
}
return instance
}
}
const getToy = proxySingletonCreate()
const toy = getToy({ name: "变形金钢" })
const toy_ = getToy({ name: "芭比娃娃" })
console.log(toy, toy_)
console.log(toy === toy_)
提供一个访问它的全局访问点。
可以采用全局对象,提供一个访问点。要处理好全局变量污染的问题。