JavaScript设计模式 - 单例模式
单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
一、实现一个标准的单例模式,用一个变量来标志当前是否已经为某个类创建过对象, 如果是,则在下一次获取该对象实例时,直接返回之前创建的对象
示例:
1 var Singleton = function(name){ 2 this.name = name; 3 this.instance = null; // 使用一个变量来表示是否已经创建该对象 4 }; 5 6 Singleton.prototype.getName = function(){ 7 console.log(this.name); 8 }; 9 10 Singleton.getInstance = function(name){ 11 if (!this.instance){ 12 this.instance = new Singleton(name); 13 } 14 return this.instance; 15 }; 16 17 var a = Singleton.getInstance("sven1"); 18 var b = Singleton.getInstance("sven2"); 19 20 console.log(a === b); // true 21 console.log(a.getName() + b.getName()); // sven1 sven1
或者另一种写法:
1 var Singleton= function(name){ 2 this.name = name; 3 }; 4 Singleton.prototype.getName = function(){ 5 console.log(this.name); 6 }; 7 8 Singleton.getInstance = (function(){ 9 var instance = null; // 是否已创建对象的标志 10 return function(name){ 11 if (!instance){ 12 instance = new Singleton(name); 13 } 14 return instance; 15 }; 16 })(); 17 18 var a = Singleton.getInstance("A"); 19 var b = Singleton.getInstance("B"); 20 21 console.log(a === b); // true 22 console.log(a.getName() + b.getName()); // A A
二、使用代理实现单利模式
下面的例子中,将使用 CreateDiv 单例类,作用是负责在页面中创建唯一的 div 节点
1 //创建 div 2 var CreateDiv = function(html){ 3 this.html = html; 4 this.init(); 5 }; 6 CreateDiv.prototype.init = function(){ 7 var div = document.createElement("div"); 8 div.innerHTML = this.html; 9 document.body.appendChild(div); 10 }; 11 12 //单例模式控制类 proxySingletonCreateDiv 13 var ProxySingletonCreateDiv = (function(){ 14 var instance = null; 15 return function(html){ 16 if (!instance){ 17 instance = new CreateDiv(html); 18 } 19 return instance; 20 } 21 })(); 22 23 var a = new ProxySingletonCreateDiv("sven1"); 24 var b = new ProxySingletonCreateDiv("sven2"); 25 console.log(a===b);
三、JavaScript 中的单例模式
单利模式的核心是确保只有一个示例,并提供全局访问
全局变量不是单例模式,但我们可以把全局变量当成单利模式来时使用;例如:
var g = {};
全局变量容易造成命名空间污染,应尽量减少全局变量的使用。减少全局污染的方法:
1. 使用命名空间
var namespace1 = { a: function(){ console.log(1); }, b: function(){ console.log(2); } };
2. 使用闭包封装私有变量
var user = (function(){ var _name = "sven", _age = 29; return { getUserInfo: function(){ return _name + "-" + _age; } } })();
私有变量被封装在闭包产生的作用域中,外界访问不到这两个变量,就可以避免对全局命令的污染
四、惰性单例
是指在我们需要的时候才可以创建对象实例。惰性单例是单例模式的重点。
示例: 这个例子中,我们把创建实例对象的职责和管理对象的职责分别放置在两个方法里,这两个方法可以独立变化而互不影响,当他们链接在一起时,就完成创建唯一实力对象的功能,看起来是一件挺奇妙的事。
1 //管理单例的逻辑代码 2 var getSingle = function(fn){ 3 var result; 4 return function(){ 5 return result || (result = fn.apply(this, arguments)) 6 } 7 }; 8 9 // 构造函数 10 var createLoginLayer = function(){ 11 var div = document.createElement("div"); 12 div.innnerHTML = "我是登陆悬浮窗"; 13 div.style.display = "none"; 14 document.body.appendChild(div); 15 return div; 16 }; 17 18 var createSingleLoginLayer = getSingle(createLoginLayer); // 创建实例的方法 19 document.getElementById("loginBtn").onclick = function(){ 20 var loginLayer = createSingleLoginLayer(); 21 loginLayer.style.display = "block"; 22 };