单例模式顾名思义就是一个类仅有一个实例,并提供一个访问它的全局访问点。 简单的代码实现如下:
const Singleton = function (name) {
this.name = name;
this.instance = null;
};
Singleton.prototype.getName = function () {
console.log(this.name);
};
Singleton.getInstance = function (name) {
return this.thisinstance || (this.thisinstance = new Singleton(name));
};
let instance1 = Singleton.getInstance('instance1');
let instance2 = Singleton.getInstance('instance2');
console.log(instance1 === instance2); // true
还有一种是将实例属性隐藏起来的实现:
const Singleton = function (name) {
this.name = name;
};
Singleton.prototype.getName = function () {
console.log(this.name);
};
Singleton.getInstance = (function () {
let instance = null;
return function (name) {
return instance || (instance = new Singleton(name));
};
})();
let instance1 = Singleton.getInstance('instance1');
let instance2 = Singleton.getInstance('instance2');
console.log(instance1 === instance2); // true
以上两种代码都能通过 Singleton.getInstance 函数实现了类的唯一创建,但是一提到类或者实例,我们还是想到直接 new 操作符的方式,这种被隐藏的创建方式多多少少让我们有点 不太习惯。所以我们需要尝试实现一个可以值直接 new 的单例模式。
const Singleton = (function () {
let instance;
const Singleton = function (name) {
if (instance) {
return instance;
}
this.name = name;
return instance = this;
};
Singleton.prototype.getName = function () {
console.log(this.name);
};
return Singleton;
})();
let instance1 = new Singleton('instance1');
let instance2 = new Singleton('instance2');
console.log(instance1 === instance2); // true
以上就是一个可以通过 new 创建实例的单例模式,如果你坚持单一职责原则的编码原则的话,也可以将以上代码职责分离,实现一个代理模式的单例模式。
const Singleton = function (name) {
this.name = name;
};
Singleton.prototype.getName = function () {
console.log(this.name);
};
const ProxySingleton = (function () {
let instance = null;
return function (name) {
return instance || (instance = new Singleton(name));
};
})();
let proxyInstance1 = new ProxySingleton('proxyInstance1');
let proxyInstance2 = new ProxySingleton('proxyInstance2');
console.log(proxyInstance1 === proxyInstance2); // true
用代理方式实现的单例模式,其实就是将基础类的实现和单例实现分离,这样的好处是基础类可以单独使用。
还可以使用 ES6 提供的 class 语法糖配合 static 关键字实现的单例模式:
class Singleton {
constructor(name) {
this.name = name;
}
getName() {
console.log(this.name);
}
static getInstance(name) {
return Singleton.instance || (Singleton.instance = new Singleton(name));
}
}
let instance1 = Singleton.getInstance('instance1');
let instance2 = Singleton.getInstance('instance2');
console.log(instance1 === instance2); // true
总结
“要实现一个标准的单例模式并不复杂,无非是用一个变量来标志当前是否已经为某个类创建过对象,如果是,则在下一次获取该类的实例时,直接返回之前创建的对象” --摘自《JavaScript设计模式与开发实践》,这是我学习设计模式过程中记录自己所得的一篇笔记,本文大部分知识理论来自《JavaScript设计模式与开发实践》。到目前为止是不是已经感觉到了 JavaScript 闭包的强大!!!