单例模式
单例模式的定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点
1. 简单实现单例模式
var SingLeon = function(name){
this.name = name
this.instance = null
}
// 原型上定义方法getName
SingLeon.prototype.getName = function(){
console.log(this.name)
}
// 定义获取实例方法 如果存在实例,就返回该实例instance,否则新建一个
SingLeon.getInstance = function(){
if(!this.instance){
this.instance = new SingLeon()
}
return this.instance
}
var a = SingLeon.getInstance('s1')
var b = SingLeon.getInstance('s2')
console.log(a == b) // true
a和b都是同一个实例 但是有相应的缺点,使用者必须知道这是一个单例模式才能使用
2.使用代理实现单例模式
var SingLeon = function(name){
this.name = name
this.getName()
}
// 原型上定义方法getName
SingLeon.prototype.getName = function(){
console.log(this.name)
}
// 引入代理类
var proxy = (function(){
var instance
return function(name){
if(!this.instance){
instance = new SingLeon(name)
}
}
})()
}
var a = SingLeon.getInstance('s1')
var b = SingLeon.getInstance('s2')
console.log(a == b) // true
这样将管理的逻辑交给代理类proxy来解决了。SingLeon只是一个普通的方法了。
3.javaSrcipt的使用方式
- 全局方式
直接var a = {} 使用全局变量符合单例模式,window.a即可访问。但是全局的缺点就不说了 - 使用命名空间
a:function(){
alert('1')
}
b:function(){
alert('1')
}
}
这样可以减少变量的使用。另外可以动态的创建全局变量。不在这里展示了。
- 使用闭包
var _name = 'name', _age = 29
return {
getUserInfo: function(){
return _name + _age
}
}
})()
这样封装到了闭包的空间里,外部访问不到,避免全局变量污染
4.惰性单例
也是单例模式中最重要的,即最开始的时候使用instance就是惰性,在调用的时候才被创建,而不是一开始就创建 举出书上登陆qq的例子
// 创建登陆
var createLoginLayer = (function(){
var div;
return function(){
// 判断是否创建过这个元素 也是重要的一点
if ( !div ){
div = document.createElement( 'div' );
div.innerHTML = '我是登录浮窗';
div.style.display = 'none';
document.body.appendChild( div );
}
return div;
}
})();
这段代码依然有缺点,即违反单一职责原则 下次创建其他的元素,例如iframe等其他,仍然要如法炮制,重新复制一遍
var getSingle = function(Fn){
var result;
return function(){
return result || (result = fn.apply(this, arguments))
}
}
将创建任何的方法当参数传入getSingle,这样可以传入createDiv,createSrcipt等等。并用result保存,如果创建过result,则直接返回result
5.vue中使用
vue2中挂载全局方法 可以根据上述登录,实现一个登陆弹窗的方法。将来会写一下