2.设计模式(单例模式)
2020-11-04 本文已影响0人
悠哈121
1.单例模式:保证一个类仅有一个实例,并且提供一个访问它的全局访问点(比如window,js中的登录窗口)
代码实现(1.增加类的不透明性,Singleton类的使用者必须知道这是一个单例类,跟以往new xxx的方式不同)
var Singleton = function( name ){
this.name = name;
};
Singleton.getInstance = (function( name ){
var instance = null
return function(name){
if(!instance){
console.log("xxx") //只会打印一次
instance = new Singleton(name)
}
return instance
}
})();
var a = Singleton.getInstance( 'sven1' );
var b = Singleton.getInstance( 'sven2' );
console.log(a === b) //true
代码实现(2.实现透明的单例类,为了把instance封装起来,我们使用了自执行的匿名函数和闭包,并且让这个匿名函数返回真正的Singleton方法,增加程序的复杂度,如果我们有一天需要利用这个类创建很多不同的对象,则要将判断地方注释掉)
var Singleton = (function(){
var instance = null;
return function(name){
if(!instance){
this.name = name;
console.log("xxx")
return instance = this
}
return instance;
}
})()
var a = new Singleton("A")
var b = new Singleton("B")
console.log(a === b,a.name) //true
代码实现(3.用代理实现单例模式,我们把负责管理单例的逻辑已到了代理类总,这样Singleton就i变成了一个普通类)
function Singleton(name){
this.name = name;
}
var proSingleton = (function(){
var instance = null;
return function(name){
if(!instance){
console.log("xxx")
instance = new Singleton(name);
}
return instance
}
})()
var a = new proSingleton("A")
var b = new proSingleton("B")
console.log(a === b) //true
js中的单例模式:js是一门无类的语言,全局变量不是单例模式,但在js开发中,经常会把全局变量当成单例使用例如 var a={},全局变量容易造成命名空间的污染
代码实现
1.使用命名空间
var namespace={
a:function(){}
}
2.使用闭包封装私有变量
let p = (function(){
let _name = "hahaha"
return {
getName:function(){
console.log(_name) //hahaha
}
}
})()
p.getName()
2.惰性单例:在需要的时候创建,而不是在页面加载好创建,比如第一部分内容所讲,再比如webqq登录窗口,点击qq头像,会弹出一个登录窗,这个浮窗在页面是唯一的,两种解决方案:1.一开始浮窗隐藏,用户点击登录的时候开始显示,这种方式有一个缺点就是在我们没有进行登录的时候,dom节点已经被创建好,可能白白浪费了dom节点,2.在单击按钮的时候再去创建登录窗口,但此时会引起dom被重复创建,于是引入一个变量判断是否创建过登录窗口
代码实现(最好把创建对象和管理单例逻辑分开,以下代码没有分开)
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;
}
})();
document.getElementById( 'loginBtn' ).onclick = function(){
var loginLayer = createLoginLayer();
loginLayer.style.display = 'block';
};