首页 > 代码库 > JS设计模式——单列模式

JS设计模式——单列模式

核心:保证一个类仅有一个实例,并提供一个访问它的全局访问点

js中的单列模式关键字:创建唯一的对象

(一)基本实现:判断是否已有实例,有则直接返回,否则生成实例

var Single = (function(){	var instance	return function(){		if(instance)return instance		return instance = this 	}})()var a = new Single()var b = new Single()console.log(a === b)

这里通过闭包,将单列对象存储在变量instance中

(二)场景:实现一个提示文本的弹出,2秒自动消失,期间再次调用错误提示时不能重复弹出 

//实现提示文本function tip(msg){	var instance = $(‘<div>‘+msg+‘</div>‘)	$(‘body‘).append(instance)	setTimeout(function(){		instance.remove()		instance = null	},2000)	return instance}

 目前这种实现是有问题的,多次调用时候会有重复div生成,我们可以根据单例模式的基本实现处理下:

//实现单例var tip_1 = (function(){	var instance	return function(msg){		if(instance)return		instance = $(‘<div>‘+msg+‘</div>‘)		$(‘body‘).append(instance)		setTimeout(function(){			instance.remove()			instance = null		},2000)	}})()

(三)通用的单例

--------通用的单例实现代码----------- function getSingle(fn){ 	let instance 	return function(){ 		return instance || (instance = fn.apply(this,arguments)) 	} }

  具体应用一:

function createLoginLayer(){	var div = document.createElement(‘div‘)	div.innerHTML = ‘I am login layer‘	div.style.display = ‘none‘	document.body.appendChild(div)	return div}var singleCreateLoginLayer = getSingle(createLoginLayer)window.onclick = function(){				var loginLayer = singleCreateLoginLayer()	loginLayer.style.display = ‘block‘}

  通过通用的单例,我们可以将单例的实现和具体业务分离开来,注意:在业务函数中一定要return返回一个具体实例,否则getSingle无效

(四)单例的扩展

  有些特殊的场景,我们需要对通用的单例模式进行扩展:

  扩展场景一:  

//按钮重复提交问题:$(document).on(‘click‘,function(){	$.ajax({		url:‘http://www.baidu.com‘,		success:function(){			console.log(‘success‘)		}	})})//优化var goAjax = function(){	return $.ajax({			url:‘http://www.baidu.com‘,			success:function(){				console.log(‘success‘)			},			error:function(){				console.log(‘error‘)			},		     })}$(document).on(‘click‘,getSingle(goAjax))

  这个优化目前存着问题,click事件只能执行一次ajax,因为第一次ajax的实例存在了就不会再去执行,所以我们这里需要能够控制到实例

function Single(){	this.instance = null}Single.prototype.getInstance = function(fn){		let _this = this	return function(){				return _this.instance || (_this.instance = fn.apply(this,arguments))	}}var goAjaxSingle = new Single()var goAjax = function(){		return $.ajax({			url:‘http://www.baidu.com‘,			success:function(){				console.log(‘success‘)				goAjaxSingle.instance = null			}		})}
$(document).on(‘click‘,goAjaxSingle.getInstance(goAjax))

  这样,在success之前,因为实例存在,所以不能被执行多次ajax

  扩展场景二:

//缓存代理场景function add(num1,num2){	return num1 + num2}var proxyFun = function(fn){	let cache = {}	return function(){		let args = [].join.call(arguments,‘,‘)		if(args in cache){			return cache[args]		}		return cache[args] = fn.apply(this,arguments)	}}var proxyAdd = proxyFun(add)proxyAdd(1,1)

  这里可以看作代理模式,也可以看作单例模式的扩展

JS设计模式——单列模式