• 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)
    

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

  • 相关阅读:
    白天写代码,晚上摆地摊!9年前摆地摊学会了这些道理...
    啪啪,打脸了!领导说:try-catch必须放在循环体外!
    阿里巴巴为什么让初始化集合时必须指定大小?
    永远不要使用双花括号初始化实例,否则就会OOM!
    限流的6大狠招,附详细代码和评测结果
    HashMap 的 7 种遍历方式与性能分析!(强烈推荐)
    String性能提升10倍的几个方法!(源码+原理分析)
    9个小技巧让你的 if else看起来更优雅
    用了自定义Banner后,SpringBoot瞬间变的高大上了...
    别再问我 new 字符串创建了几个对象了!我来证明给你看!
  • 原文地址:https://www.cnblogs.com/webLilingyun/p/6549519.html
Copyright © 2020-2023  润新知