什么是单例模式

单例模式,也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。

单例模式的定义比较好理解,就是在应用程序中单例对象的类只有一个实例存在。

举例说明

对于单例模式的事例,使用java这种强类型的语言是最容易去展示的。因为对于一个类而言,我们知道每new一下,它就会有一个新的实例,如果要完美的保证他只有一个实例的话,那么最好的解决方案就是让这个类在外部无法被new出来。让这个类的实例只能通过这个类本身的方法来生成。

但是对于JavaScript来说,因为它不是一个强类型的语言,他没有private这种关键词,所以说,他没有办法来限制,外部代码通过new关键字来创建实例。但是这并不影响单例模式在JavaScript中的应用,关于单例模式的使用场景我们在本章的后面再说,还是先来看我为大家准备的这个事例。

单例模式的例子非常简单:全世界那么多的人,你只有一个对吧。我们可以通过new关键字来创建一个又一个的人,但他们都不是你对吧。

绘制UML类图

在这里插入图片描述

这就是我绘制出来的单例模式下的UML类图,他只有一个类SingleObjcet,我们给他一个名字的属性作为标记,然后- SingleObject()表示这是一个私有的构造函数,不应该被new出来,虽然我们在JavaScript中无法防止它被new,但是我们可以在UML类图中对它进行表示。getInstance()返回一个SingleObject实例,也就是程序中的单例对象。接下来我们通过代码来实现一下。

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class SingleObject {
constructor (name) {
this.name = name || '路人甲乙丙';
}

getName () {
return this.name;
}
}

SingleObject.getInstance = function () {
let instance = null;

return function () {
if (instance === null) {
instance = new SingleObject('LGD_Sunday');
}
return instance;
}
}();


const s1 = SingleObject.getInstance();
console.log(s1.getName());// LGD_Sunday
const s2 = SingleObject.getInstance();
console.log(s2.getName());// LGD_Sunday
console.log(`s1 === s2 ${s1 === s2}`); // true

const s3 = new SingleObject();
console.log(s3.getName());// 路人甲乙丙
console.log(`s1 === s3 ${s1 === s3}`); // false

在上面的代码中SingleObject就是我们的单例类,而SingleObject.getInstance这个属性方法就是SingleObject去生成单例对象的方法。在下面的验证代码中,我们可以看出s1s2都是同一个实例对象。同样的我们唯一的缺陷就是无法避免s3的创建,这是由JavaScript语言的特性来决定的。

应用场景

JavaScript中,有哪些场景下使用到了单例模式?大家想一下,window对象是不是一个单例模式?是的。window就是在JavaScript中的一个典型的单例模式的应用。我们在JavaScript中的所有的全局变量变量都会被保存到window下面,如果window不是单例的,那么我们整个JavaScript的全局逻辑也就都不存在了。

除了window之外呢?还有哪些?还有一个比较典型的例子就是:登录用户信息userModel。如果大家开发过webapp的话,那么应该会对这个概念比较熟悉,其实所谓userModel就是在应用全局保存的登录用户的信息,可以包括用户名称、用户ID、用户的购物车等等等等。。。并且它应该是唯一的。那么要实现这个userModel我们应该怎么做?一般情况下实现userModel的方式有两种:

  1. window.userModel:不过在JavaScript的逻辑中,我们应该尽量避免污染全局变量,所以我们应该尽量不要直接把userModel挂载到window对象上,所以这种方式应该作为不得已的选择。
  2. 单例模式:我们可以通过单例模式来实现一个全局唯一的userModel,确保我们在任何一个地方都可以获取到唯一的登录用户信息,并不会污染全局空间。

总结

单例模式在任何一个面向对象的语言中都有很重要的作用,他的主要作用是确保创建的对象在整个应用中为唯一的。当我们需要在应用中创建具有唯一性的对象的时候,为了避免污染全局空间,我们就可以使用单例模式。比如:userModel、登录框、购物车等等