摘要:本系列为设计模式与开发实践作者曾探学习总结,如想深入了解,请支持作者原版单例模式实现单例模式单例模式的定义是保证一个类仅有一个实例,并提供一个访问它的全局访问点。
本系列为《JavaScript设计模式与开发实践》(作者:曾探)学习总结,如想深入了解,请支持作者原版
单例模式 实现单例模式单例模式的定义是:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
单例模式是一种常用的模式,有一些对象我们往往只需要一个,比如登录窗口,这个窗口是唯一的,无论我们点击多少次登录按钮,这个窗口只会被创建一次,那么这个窗口就适合用单例模式来创建。
要实现一个标准的单例模式并不复杂,无非是用一个变量来标志当前是否已经为某个类创建过对象,如果是,则在下一次获取该类的实例时,直接返回之前创建的对象。代码如下:
</>复制代码
var Singleton=function(name){
this.name=name;
this.instance=null;
};
Singleton.prototype.getName=function(){
alert(this.name);
};
Singleton.getInstance=function(){
if(!this.instance){
this.instance=new Singleton(name);
}
return this.instance;
};
var a=Singleton.getInstance("sven1");
var b=Singleton.getInstance("sven2");
alert(a===b);//true
或者
</>复制代码
var Singleton=function(name){
this.name=name;
};
Singleton.prototype.getName=function(){
alert(this.name);
};
Singleton.getInstance=(function(){
var instance=null;
return function(name){
if(!instance){
instance=new Singleton(name);
}
return instance;
}
})();
我们通过Singleton.getInstance来获取Singleton类的唯一对象,这种方式相对简单,但是不透明。跟以往通过new XXX的方式获取对象不同,这里偏要使用Singleton.getInstance来获取对象,所以这段代码的意义并不大。
透明的单例模式我们现在的目标是实现一个透明的单例类。
</>复制代码
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("sven1");
var b = new CreateDiv("sven2");
alert(a===b);//true
虽然现在完成了一个透明的单例类的编写,但它同样有一些缺点。为了把instance封装起来,我们使用了自执行的匿名函数和闭包,并且让这个匿名函数返回真正的Singleton构造方法,这增加了一些程序的复杂度,阅读起来也不是很舒服。
假设我们某天需要让这个单例类变成一个普通的类,即可以产生多个实例,那我们必须改写CreateDiv构造函数,这种修改会带来很多不必要的麻烦。
我们首先创建一个普通的CreateDiv类:
</>复制代码
var CreateDiv = function(html) {
this.html = html;
this.init();
};
CreateDiv.prototype.init = function() {
var div = document.createElement("div");
div.innerHtml = this.html;
document.body.appendChild(div);
};
接下来引入代理类ProxySingletonCreate:
</>复制代码
var ProxySingletonCreate = (function() {
var instance;
return function(html) {
if (!instance) {
instance = new CreateDiv(html);
}
return instance;
}
})();
var a = new ProxySingletonCreate("sven1");
var b = new ProxySingletonCreate("sven2");
console.log(a === b);
这样一来,CreateDiv和ProxySingletonCreate组合起来,实现了单例模式的效果。
JavaScript中的单例模式前面提到的几种单例模式的实现,更多的是接近传统面向对象语言中的实现,单例对象从类中创建而来。但JavaScript其实是一门无类的语言,所以生搬单例模式的概念并无意义。
单例模式的核心是:确保只有一个实例,并提供全局访问。
全局变量不是单例模式,但在实际应用中,我们经常会把全局变量当成单例来使用。
例如:
</>复制代码
var a = {};
全局变量可以满足上述的两个条件,但却存在许多问题:它很容易造成命名空间污染。作为普通的开发者,我们有必要减少全局变量的使用,一下几种方式可以相对降低全局变量带来的命名污染。
使用命名空间最简单的方法依然是使用对象字面量方式:
</>复制代码
var namespace1={
a:function(){
},
b:function(){
}
};
我们还可以动态的创建命名空间:
</>复制代码
var myApp = {};
myApp.namespace = function(name) {
var parts = name.split(".");
var current = myApp;
for (var i in parts) {
if (!current[parts[i]]) {
current[parts[i]] = {};
}
current = current[parts[i]];
}
};
myApp.namespace("event");
myApp.namespace("dom.style");
console.log(myApp);
使用闭包封装私有变量
</>复制代码
var user=(function(){
var _name="sven",_age=29;
return {
getUserInfo:function(){
return _name+"_"+_age;
}
}
})();
惰性单例
惰性单例指的是在需要的时候才创建对象实例。惰性单例是单例模式的重点,这种技术在实际开发中非常有用。
我们先抽取出一个管理单例的逻辑对象:
</>复制代码
var getSingle=function(fn){
var result;
return function(){
return result||(result=fn.apply(this.arguments));
}
};
创建对象的方法fn被当做参数传入getSingle。
</>复制代码
var getSingle = function(fn) {
var result;
return function() {
return result || (result = fn.apply(this.arguments));
};
};
var createLoginLayer = function() {
var div = document.createElement("div");
div.innerHTML = "我是登录窗";
div.style.width = "100px";
div.style.height = "100px";
div.style.background = "red";
document.body.appendChild(div);
return div;
};
aa = getSingle(createLoginLayer);
aa();
result变量因为身在闭包中,永远不会被销毁。在将来的请求中,如果result已经被赋值,那么他将返回这个值。
以下是演示地址:
惰性单例演示地址
其他演示地址
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/78844.html
摘要:所以程序在引入文件的时候用了单例模式,一个文件实例化一次,这种做法无疑是好的,但是也容易引起。在我们平时的开发过程中,可以借鉴这两种方式去缓存变量,节点等。 这一章作者讲了一个例子,就是在用单例模式生成一个dom节点,还要做到只有访问的时候才创建,后续访问直接用前面创建的。那么实际开发中我们会用到这个模式吗?现在我们基本都是用vue,react,angular开发,不太会直接去操作do...
摘要:大潮来袭前端开发能做些什么去年谷歌和火狐针对提出了的标准,顾名思义,即的体验方式,我们可以戴着头显享受沉浸式的网页,新的标准让我们可以使用语言来开发。 VR 大潮来袭 --- 前端开发能做些什么 去年谷歌和火狐针对 WebVR 提出了 WebVR API 的标准,顾名思义,WebVR 即 web + VR 的体验方式,我们可以戴着头显享受沉浸式的网页,新的 API 标准让我们可以使用 ...
阅读 3914·2021-11-15 11:37
阅读 2387·2021-09-24 10:39
阅读 2652·2021-07-25 21:37
阅读 1640·2019-08-30 15:56
阅读 2643·2019-08-30 15:55
阅读 1030·2019-08-30 15:54
阅读 2197·2019-08-30 14:21
阅读 918·2019-08-30 11:24