上一章后续的内容是关于 JS 函数闭包的,考虑很多读者已经有了闭包基础或者希望通过实战理解,遂跳过上一章直接开始设计模式篇~
需要注意的是,代码部分仅供参考,主要关注的内容是设计模式的思想和运用,结合到自己的实战中才是最好的
单例模式
单例模式的定义是:保证一个类只有一个实例,并提供一个访问他的全局访问点
例如:线程池,全局缓存,登陆窗口(无论你点击多少次,窗口都只会创建一个)
实现
实现起来并不复杂,只需要创建一个变量来标识是否已经为某个类创建过对象,如果已经创建了,那就直接返回之前创建的对象~
const Singleton = {
instance: null,
getInstance: function () {
if (!this.instance) {
this.instance = {
// 在这里定义单例的属性和方法
name: "Singleton Instance",
sayHello: function () {
console.log("Hello from Singleton!");
},
};
}
return this.instance;
},
};
// 使用示例
const instance1 = Singleton.getInstance();
console.log(instance1.name); // 输出: Singleton Instance
instance1.sayHello(); // 输出: Hello from Singleton!
const instance2 = Singleton.getInstance();
console.log(instance2.name); // 输出: Singleton Instance
console.log(instance1 === instance2); // 输出: true
方便结合理解,我们加入一个静态型面向对象的语言 C# 来看:
public class Singleton
{
private static Singleton instance;
// 私有构造函数,防止外部实例化
private Singleton()
{
}
public static Singleton Instance
{
get
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
// 在这里定义单例的其他属性和方法
public string Name { get; set; }
public void SayHello()
{
Console.WriteLine("Hello from Singleton!");
}
}
代理单例
上面的代码有一个问题,你会发现 JS 部分中,一部分代码用来保证单例不重复创建,另一部分代码用来创建单例对象,显然这不是一个好的做法,如果某一天我们要改写这个单例代码,无疑会使代码变得复杂,所以引入 代理 单例模式
通过这样就使得 Singleton 成为了一个普通的类,和 Proxy 组成了单例模式!
var Singleton = function () {
this.name = "Singleton Instance";
};
Singleton.prototype.sayHello = function () {
console.log("Hello from Singleton!");
};
const SingletonProxy = (function () {
var instance;
return function () {
if (!instance) {
instance = new Singleton();
}
return instance;
};
})();
// 使用示例
var proxyInstance1 = new SingletonProxy();
var proxyInstance2 = new SingletonProxy();
console.log(proxyInstance1.name);
console.log(proxyInstance2.name);
同样还有 C# 版的:
private class Singleton
{
private Singleton()
{
// 构造函数
}
}
public class SingletonProxy
{
private Singleton proxyInstance;
public Singleton GetInstance()
{
if (proxyInstance == null)
{
proxyInstance = Singleton.Instance;
}
return proxyInstance;
}
}
惰性单例
上面的代码已经实现了惰性单例模式:只有调用的时候才实现对象的初始化,即这一段:
public Singleton GetInstance()
{
if (proxyInstance == null)
{
proxyInstance = Singleton.Instance;
}
return proxyInstance;
}
这样使得资源和配置更灵活,且线程安全~