TypeScript 实现单例模式
Posted: 09.28.2019
介绍
特性
每个类都只有一个唯一的实例化的对象,并提供一个全局访问点。
应用场景
- 需要生成唯一序列的环境
- 需要频繁实例化然后销毁的对象。
- 创建对象时耗时过多或者耗资源过多,但又经常用到的对象。
- 方便资源相互通信的环境
例子1:
在我们的 Windows 桌面上,我们打开了一个回收站,当我们试图再次打开一个新的回收站时,Windows 系统并不会为你弹出一个新的回收站窗口。也就是说在整个系统运行的过程中,系统只维护一个回收站的实例。新建一个新的回收站是没有意义的,因为回收站间资源共享,因此需要单例模式。
例子2:
再举一个例子,网站的计数器,一般也是采用单例模式实现,如果你存在多个计数器,每一个用户的访问都刷新计数器的值,这样的话你的实计数的值是难以同步的。但是如果采用单例模式实现就不会存在这样的问题,而且还可以避免线程安全问题。同样多线程的线程池的设计一般也是采用单例模式,这是由于线程池需要方便对池中的线程进行控制。
代码实现
饿汉式
在初始化的时候,直接创建实例。
class Singleton {
// 实例作为静态的私有属性
private static instance: Singleton = new Singleton();
public name: string;
// 构造函数为私有的
private constructor(name: string = 'Lynch') {
this.name = name;
}
// 向外输出实例的,只有这一个静态的方法
public static getInstance() {
return this.instance;
}
}
// 输出 Lynch
let single = Singleton.getInstance();
console.log(single.name);
// 输出 true,因为 single 和 single2 指向同一个实例
let single2 = Singleton.getInstance();
console.log(single === single2);
// 都会输出 Sucker
single.name = 'Sucker';
console.log(single.name);
console.log(single2.name);
懒汉式
在初始化类的时候,不创建实例,而是等到真正需要用到的时候才创建。
Java 由于多线程的存在,需要设置 synchronized 或者加锁,JS 就不需要这么做了。
class Singleton {
// 实例作为静态的私有属性
private static instance: Singleton;
public name: string;
// 构造函数为私有的
private constructor(name: string) {
this.name = name;
}
// 向外输出实例的,只有这一个静态的方法
public static getInstance(name: string = 'Lynch') {
if (!this.instance) {
this.instance = new Singleton(name);
}
return this.instance;
}
}
// 输出 Alice
let single = Singleton.getInstance('Alice');
console.log(single.name);
// 输出 true,因为 single 和 single2 指向同一个实例
let single2 = Singleton.getInstance();
console.log(single === single2);
// 都会输出 Sucker
single.name = 'Sucker';
console.log(single.name);
console.log(single2.name);
参考资料
单例模式,懒汉饿汉,线程安全,double checked locking的问题