单例:就是单个实例的意思。
核心思想:第一次new的时候返回实例对象,并且保存这个实例对象,后面不管你new多少次,返回的都是那个被保存的实例对象。这种设计模式适用于整个系统只需要拥有一个全局对象,这样才有利于协调系统整体的行为。
基本实现方式
function Singleton(name) {
this.name = name
}
Singleton.prototype.getName = function () {
return this.name
}
var instance = null
Singleton.getInstance = function (name) {
if (instance) return instance
return instance = new Singleton(name)
}
var s1 = Singleton.getInstance('张三')
var s2 = Singleton.getInstance('李四')
console.log(s1 === s2) // true
可以看到s1和s2完全相等,达到了我们预期的效果。但是这种做法有两点不好的地方,第一点,我们没有去直接new,而是通过getInstance来获取实例的,这样不友好。第二点instance这个变量存在了全局作用域的位置,这也是不友好的,如果能直接访问到instance,那我们还去new干嘛呢,所以这样也是不友好的,这时候闭包的优势就来了。
闭包实现
var Singleton = (function() {
var instance = null
function SingletonHelper(name) {
if (instance) return instance
this.name = name
return instance = this
}
SingletonHelper.prototype.getName = function () {
return this.name
}
return SingletonHelper
})()
var s1 = new Singleton('张三')
var s2 = new Singleton('李四')
console.log(s1 === s2); // true
console.log(s1.getName()); // 张三
这样就可以正常的去new 一些对象,而且不管你new 几个,结果都是一样的,都是第一个生成的那个对象。当然这个也有缺点,不符合单一职责原则,这个对象负责了两个功能,单例和创建对象。那我们用代理试试。
代理实现单例
function Animal(name) {
this.name = name
}
Animal.prototype.getName = function () {
return this.name
}
var Singleton = (function () {
var instance = null
var SingletonHelper = function (name) {
if (instance) return instance
return instance = new Animal(name)
}
return SingletonHelper
})()
var s1 = new Singleton('张三')
var s2 = new Singleton('李四')
console.log(s1 === s2); // true
console.log(s1.getName()); // 张三
是不是很完美,但是这还是有缺点,代码不能复用,如果其它对象也要单例设计模式,还得再从新写一份
通用单例设计模式
function Animal(name) {
this.name = name
}
Animal.prototype.getName = function() {
return this.name
}
var Singleton = function(obj) {
var instance = null
var SingletonHelper = function() {
if(instance) return instance
return instance = new obj(arguments)
}
return SingletonHelper
}
var AnimalSingleton = new Singleton(Animal)
var s1 = new AnimalSingleton('小狗')
var s2 = new AnimalSingleton('小猫')
console.log(s1 === s2); // true
console.log(s1.getName()); // Arguments ["小狗", callee: ƒ, Symbol(Symbol.iterator): ƒ]
es6单例设计模式
class People {
constructor(name) {
if (typeof People.instance === 'object') {
return People.instance;
}
People.instance = this;
this.name = name
return this;
}
}
var a = new People('a')
var b = new People('b')
console.log(a === b) // true