定义
单例模式(Singleton Pattern):单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。单例模式又名单体模式。
单例模式的要点有三个:
- 某个类只能有一个实例;
- 它必须自行创建这个实例;
- 它必须自行向整个系统提供这个实例。
单例模式是一种常见的模式,也比较简单。比如线程池、全局缓存、浏览器的window对象等。
作用
减少反复创建和销毁相同对象的成本。
举例
要实现一个标准的单例模式不复杂,就是用一个变量instance来标志是否已经创建过对象,如果是则下次直接返回该类的实例。
var Singleton = function (name) {
this.name = name;
this.instance = null;
}
Singleton.prototype.getName = function () {
console.log(this.name);
}
Singleton.getInstance = function (name) {
if (!this.instance) {
this.instance = new Singleton(name);
}
return this.instance;
};
var a = Singleton.getInstance('jour01');
var b = Singleton.getInstance('jour02');
console.log(a === b); // true
复制代码
上面我们已经实现了单例模式,但是Singleton.getInstance
这个写法很花里胡哨。这增加了不透明性,我们们必须知道这个类是单例类才能这么用。我们优化下这个实例,通过代理模式重写:
var Singleton = function (name) {
this.name = name;
}
Singleton.prototype.getName = function () {
console.log(this.name);
}
var ProxySingleton = (function () {
var instance;
return function (name) {
if (!instance) {
instance = new Singleton(name);
}
return instance;
}
})();
var a = new ProxySingleton('jour01');
var b = new ProxySingleton('jour02');
console.log(a === b); // true
复制代码
JS中单例模式就更简单了:
var obj = {};
复制代码
obj
是个全局变量,也是单例对象。是独一无二的,且全局都可以访问。但这是很糟糕的写法,污染了全局空间,容易造成冲突。
惰性单例
惰性单例指的是在需要的时候才创建对象实例。下面通过实现一个登录弹窗来说明惰性单例的作用:
<html>
<body>
<button id="loginBtn">登录</button>
</body>
</html>
复制代码
var createLoginLayer = function () {
var div = document.createElement('div');
div.innerHTML = '登录窗口';
div.style.display = 'none';
document.body.appendChild(div);
return div;
}
var proxySingletonLayer = (function () {
var instance;
return function () {
if (!instance) {
instance = createLoginLayer();
}
return instance;
}
})();
document.getElementById('loginBtn').onclick = function () {
var loginLayer = proxySingletonLayer();
loginLayer.style.display = 'block';
}
复制代码
优点
- 提供了对唯一实例的受控访问。因为单例类封装了它的唯一实例,所以它可以严格控制客户怎样以及何时访问它,并为设计及开发团队提供了共享的概念。
- 由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象,单例模式无疑可以提高系统的性能。
缺点
- 由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。
- 单例类的职责过重,在一定程度上违背了“单一职责原则”。因为单例类既充当了工厂角色,提供了工厂方法,同时又充当了产品角色,包含一些业务方法,将产品的创建和产品的本身的功能融合到一起。
小结
单例模式是一种简单但是非常实用的模式,特别是惰性单例,在合适的时候才创建对象,并且只创建唯一的一个。创建对象和管理单例的职责被分布在两个不同的方法中,更具威力。
该系列文章关注博客!