设计模式之单例模式

单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点!

例如 有些对象我们往往只需要一个,比如线程池、全局缓存、浏览器中的window对象、jq对象等。我们在登录的时候登录的浮窗,无论我们点了多少次登录 浮窗只会被创建一次 这个浮窗我们就可以用单列模式来创建。
1.简单实现下单例模式
思路:用一个类创建对象,如果下次再次使用该类的实例对象的时候,直接返回之前的对象,,要通过一个变量来记录是否为某类创建过对象

var a=function(name){
	this.name=name
	this.instance=null
};
a.prototype.getName = function(){
	alert(this.name)
}
a.getInstance = function(name){
	if(!this.instance){
		this.instance = new a(name)
	}
	return this.instance
}

var b = a.getInstance('zhangsan')
var c = a.getInstance('lisi')
alert(b=== c)  //?     true

2.‘透明’的单例模式
目标:实现一个‘透明’的单例类。从这个类中创建对象的时候,可以像使用其他任何普通类一样
需求:在页面上中创建卫衣的div节点,借助单例模式的思想

var CreateDiv = (function(){
	var instance;
	var CreateDiv = function(html){
		if(instance){
			return instance
		}
		this.html = html
		this.init()
		return instance = this
	}
	CreateDiv.prototype.init = function (){
		var div = document.CreateElement('div')
		div.innerHTML = this.html
		document.body.appendChild(div)
	}
	
	return CreateDiv
})
var a = new CreateDiv('zhangsan')
var b = new CreateDiv('lisi')

elert(a===b)  //?       true

简单实现了上面的需求跟目标,看代码能发现一些缺点

//现在的Singleton构造函数
var CreateDiv = function(html){
	if(instance){
		return instance
	}
	this.html = html
	this.init()
	return instance = this
}

为了把instance封装起来,我们使用了自执行函数的匿名函数和闭包 并且让这个匿名函数返回真正的Singleton构造函数, 在一定程度上增加了 程序的复杂程度 不易阅读
CreateDiv 的构造函数主要负责了两件事 1、创建对象和执行初始化函数 2.保证只有一个对象实例。假如 有一天我们利用这个类创建千千万万个DIV,即要让这个类 从单例类 变成 一个普通的 可以创建多个实例的类,那我们必须要改写CreateDiv 构造函数,去掉控制创建唯一对象的那一层去掉,这种修改也会给我们带来别的麻烦。
3.用代理实现单例模式
引入代理类的概念,主要是解决上面提到的问题。
通过2后面提出的问题 对CreateDiv 构造函数进行改造 把单例的代码移除 是它成为一个普通的创建DIV的类;

var CreateDiv = function(html){
	this.html = html
	this.init()
	return instance = this
}
CreateDiv.prototype.init = function (){
	var div = document.CreateElement('div')
	div.innerHTML = this.html
	document.body.appendChild(div)
}

接着引入代理类 PrototypeCreateDiv

var PrototypeCreateDiv = (function(){
	var instance;
	return function( html ){
		if( !instance ) {
			instance = new CreateDiv( html );
		}
		return instance
	}
})();
var a = new PrototypeCreateDiv('zhangsan')
var b = new PrototypeCreateDiv('lisi')
alert(a===b) //?     true

引入代理类的方式 ,我们同样也完成了一个单例模式的编写,跟之前不同的是 现在我们把负责管理单例的逻辑 移到了 代理类 PrototypeCreateDiv 中。CreateDiv的也变成了一个普通的类,它与PrototypeCreateDiv 组合起来 达到单例模式的效果!(这个也是缓存代理的应用之一)

参考文献 :JavaScript设计模式与开发实践

posted @ 2021-10-31 20:35  xiao旭  阅读(40)  评论(0编辑  收藏  举报