javascript---设计模式之单体模式(一)
单体是一个用来划分命名空间并将一些相关的属性与方法组织在一起的对象,如果她可以被实例化的话,那她只能被实例化一次(她只能嫁一次,不能二婚)。
单体模式是javascript里面最基本但也是最有用的模式之一。
特点:1.可以用来划分命名空间,从而清除全局变量所带来的危险或影响。
2.利用分支技术来来封装浏览器之间的差异。
3.可以把代码组织的更为一体,便于阅读和维护。
单体模式的基本写法:
复制代码
/最基本的单体模式/
varher={
name:''Anna'',
sex:''women'',
say:function(){
//一些处理逻辑......
},
doing:function(){
//另一些处理函数......
}
}
复制代码
1.划分命名空间:
复制代码
varbox={
width:0,
height:0,
getArea:function(){
returnthis.widththis.width;//js中对象成的访问必须是显示的,即this是不能省略的
},
init:function(w,h){
//width=w;
//height=h;这种方式相当于定义了两个全局变量,(没加var声明的变量为全局变量)
//并不是对对象width和height的赋值
//下面是正确的
this.width=w;
this.height=h;
}
}//box划分了一个命名空间,命名空间里的变量只在空间里有效
复制代码
上面的单体中的所有的成员以及方法都是公有的(public),也就是在单体的外部可以对她们进行任意的改动(但不能访问其中的局部变量),那为什么说单体提供了一个命名空间呢?
别急,我们接着往下看:
复制代码
varbox={
width:0,
height:0,//单体的变量
getArea:function(){
returnwidthheight;//width,height其实并不是单体的变量,而是在init中定义的全局变量
}
init:function(w,h){
width=w;
height=h;
}
}//init中width,height其实并不是单体的变量
window.onload=function(){
varinit=box.getArea();
alert(init);
}
复制代码
由于没有对init中的width,height进行初始化,所以会报错,这样改一下:
复制代码
varbox={
width:0,
height:0,
getArea:function(){
returnwidthheight;
},
init:function(w,h){
width=w;
height=h;
}
}
window.onload=function(){
width=0;
height=0;
//orbox.init(0,0);
varinit=box.getArea();
alert(init);
}
复制代码
发现可以了,由于init和getArea所用的width和height并不是归单体所有的变量,而是一个全局变量,所以我们可以在单体外面进行随意调用而不受影响、
复制代码
varbox={
width:0,
height:0,
getArea:function(){
returnwidthheight;//js中对象成的访问必须是显示的,即this是不能省略的
},
init:function(w,h){
width=w;
height=h;
}
}//这里的width,height其实并不是单体的对象
window.onload=function(){
width=0;
height=0;
varwidth=box.getArea();
alert(width);
}
复制代码
这样写又会报错了,可见我们以上的方式对于全局变量并没有建立起一个命名空间,全局变量为我们带来了危险。所以最上面的写法是对的,我们来验证一下:
复制代码
varbox={
width:2,
height:2,
getArea:function(){
returnthis.widththis.height;//js中对象成的访问必须是显示的,即this是不能省略的
},
init:function(w,h){
this.width=w;
this.height=h;
}
}
window.onload=function(){
width=0;//不会影响单体中的局部变量也就是命名空间
height=0;//不会影响单体中的局部变量也就是命名空间
varwidth=box.getArea();
alert(width);
}
复制代码
可见在window.onload中的width和height已经没有干扰了,因为单体为单体中的width和height建立了一个命名空间。
2.成员的属性:
虽然在javascript中没有这么严格的面向对象(oop),但是我们可以借助闭包来进行一个模仿,毕竟有的变量设为public是很不好的。
复制代码
varher=(function(){
varname=''Anna'';
varsex=''women'';
return{
getArea:function(){
returnname+''isa''+sex;
},
init:function(b){
name=b;
}
}
})();
window.onload=function(){
her.name=''Jock'';//无法访问
alert(ger.getArea());
her.init(''Lous'');
alert(her.getArea());
}
复制代码
私有变量、方法是只读的,公有变量、方法是可读可写的。
访问:
对于私有成员,直接访问即可,前面不用加任何修饰,
对于公有的访问在单体作用域内前面要加上“this.”,在单体作用域外前面要加上“her.”(单体名字.)
3.利用分支技术来来封装浏览器之间的差异
注意的地方:
a.一定要用闭包,实现即时绑定
b.每个分支之间用分号隔开
c.最后返回的是分支的名字
d.调用的时候用单体名+分支的方法名;
复制代码
//利用单体的分支技术来定义XHR(XMLHttpRequest)对象,必须要用闭包才可以实现
varXHR=(function(){
//Thethreebranches
varstandard={
cXHR:function(){
returnnewXMLHttpRequest();
}
};
varactiveXNew={
cXHR:function(){
returnnewActiveXObject(''Msxml2.XMLHttp'');
}
};
varactiveXOld={
cXHR:function(){
returnnewActiveXObject(''Microsoft.XMLHttp'');
}
};
//Toassign(分配)thebranch,tryeachmethod;returnwhateverdoesn''tfail
vartestObject;
try{
testObject=standard.cXHR();
returnwww.wang027.comstandard;//returnthisbranchifno
errorwasthrown}catch(e){
try{
testObject=activeXNew.cXHR();
returnactiveXNew;
}catch(e){
try{
testObject=activeXOld.cXHR();
returnactiveXOld;
}catch(e){
thrownewError(''CreatetheXMLHttpRequestObjectfailed!'');
}
}
}
})();
window.onload=function(){
alert(XHR.cXHR());
}
|
|