javascript设计模式之单体模式
单体是一个用来划分命名空间并将一批相关的属性和方法组织在一起的对象,如果他可以被实例化,那么他只能被实例化一次。
单体模式是javascript里面最基本但也是最有用的模式之一。
特点:
1. 可以来划分命名空间,从而清除全局变量所带来的危险。
2. 利用分支技术来来封装浏览器之间的差异。
3.
可以把代码组织的更为一体,便于阅读和维护。
单体的基本结构(正确写法):
/*Basic Singleton*/
var Singleton = {
attribute1:true,
attribute2:10,
method1:function(){},
method2:function(){}
};
var Singleton = {
attribute1:true,
attribute2:10,
method1:function(){},
method2:function(){}
};
1划分命名空间:
1 var box = {
2 width:0,
3 height:0,
4 getArea:function(){
5 return this.width*this.height;//js中对象成的访问必须是显示的,即this是不能省略的
6 },
7 init:function(w,h){
8 // width = w;
9 // height = h;这种方式相当于定义了两个全局变量,(没加var声明的变量为全局变量)
10 // 并不是对对象width和height的赋值
11 //下面是正确的
12 this.width = w;
13 this.height = h;
14 }
15 }//box划分了一个命名空间,命名空间里的变量只在空间里有效
16
2 width:0,
3 height:0,
4 getArea:function(){
5 return this.width*this.height;//js中对象成的访问必须是显示的,即this是不能省略的
6 },
7 init:function(w,h){
8 // width = w;
9 // height = h;这种方式相当于定义了两个全局变量,(没加var声明的变量为全局变量)
10 // 并不是对对象width和height的赋值
11 //下面是正确的
12 this.width = w;
13 this.height = h;
14 }
15 }//box划分了一个命名空间,命名空间里的变量只在空间里有效
16
我们继续:
1 var box = {
2 width:0,
3 height:0,//单体的变量
4 getArea:function(){
5 return width*height;//中的,width,height其实并不是单体的变量,而是在init中定义的全局变量
6 }
7 init:function(w,h){
8 width = w;
9 height = h;
10 }
11 }//init中width,height其实并不是单体的变量
12 window.onload = function(){
13 var init = box.getArea();
14 alert(init);
15 }
2 width:0,
3 height:0,//单体的变量
4 getArea:function(){
5 return width*height;//中的,width,height其实并不是单体的变量,而是在init中定义的全局变量
6 }
7 init:function(w,h){
8 width = w;
9 height = h;
10 }
11 }//init中width,height其实并不是单体的变量
12 window.onload = function(){
13 var init = box.getArea();
14 alert(init);
15 }
1 var box = {
2 width:0,
3 height:0,
4 getArea:function(){
5 return width*height;
6 },
7 init:function(w,h){
8 width = w;
9 height = h;
10 }
11 }
12 window.onload = function(){
13 width = 0;
14 height = 0;
15 //or box.init(0,0);
16 var init = box.getArea();
17 alert(init);
18 }
2 width:0,
3 height:0,
4 getArea:function(){
5 return width*height;
6 },
7 init:function(w,h){
8 width = w;
9 height = h;
10 }
11 }
12 window.onload = function(){
13 width = 0;
14 height = 0;
15 //or box.init(0,0);
16 var init = box.getArea();
17 alert(init);
18 }
如果我们这样写一下就更明白了:
1 var box = {
2 width:0,
3 height:0,
4 getArea:function(){
5 return width*height;//js中对象成的访问必须是显示的,即this是不能省略的
6 },
7 init:function(w,h){
8 width = w;
9 height = h;
10 }
11 }//这里的width,height其实并不是单体的对象
12 window.onload = function(){
13 width = 0;
14 height = 0;
15 var width = box.getArea();
16 alert(width);
17 }
2 width:0,
3 height:0,
4 getArea:function(){
5 return width*height;//js中对象成的访问必须是显示的,即this是不能省略的
6 },
7 init:function(w,h){
8 width = w;
9 height = h;
10 }
11 }//这里的width,height其实并不是单体的对象
12 window.onload = function(){
13 width = 0;
14 height = 0;
15 var width = box.getArea();
16 alert(width);
17 }
1 var box = {
2 width:2,
3 height:2,
4 getArea:function(){
5 return this.width*this.height;//js中对象成的访问必须是显示的,即this是不能省略的
6 },
7 init:function(w,h){
8 this.width = w;
9 this.height = h;
10 }
11 }
12 window.onload = function(){
13 width = 0;
14 height = 0;
15 var width = box.getArea();
16 alert(width);
17 }
2 width:2,
3 height:2,
4 getArea:function(){
5 return this.width*this.height;//js中对象成的访问必须是显示的,即this是不能省略的
6 },
7 init:function(w,h){
8 this.width = w;
9 this.height = h;
10 }
11 }
12 window.onload = function(){
13 width = 0;
14 height = 0;
15 var width = box.getArea();
16 alert(width);
17 }
2成员的属性:
讨论完命名空间,我们来对单体变量和方法的属性做一下设定。学过其他语言的人(java,c++,c#...)都应该很了解其中类成员的public和private,
虽然在javascript中没有这么严格的面向对象(oop),但是我们可以借助闭包来进行一个模仿,毕竟有的变量设为public是很不好的。
1 var circle = (function(){
2 //pravite member!
3 var r = 5;
4 var pi = 3.1416;//后面用分号
5 return{//public member
6 getArea:function(){
7 return r*r*pi;//访问私有成员不要加this
8 },//后面用逗号
9 //如果想改变r和pi的值,只能通过设置一个公有的函数来实现
10 init:function(setR){
11 r = setR;
12 }
13 }
14 })()
15 window.onload = function(){
16 circle.r = 0;//无法访问私有成员,相当于又为circle创建了一个共有成员r
17 alert(circle.getArea());
18 circle.init(0);//通过公有的工具函数便可以访问了。
19 alert(circle.getArea());
20 };
2 //pravite member!
3 var r = 5;
4 var pi = 3.1416;//后面用分号
5 return{//public member
6 getArea:function(){
7 return r*r*pi;//访问私有成员不要加this
8 },//后面用逗号
9 //如果想改变r和pi的值,只能通过设置一个公有的函数来实现
10 init:function(setR){
11 r = setR;
12 }
13 }
14 })()
15 window.onload = function(){
16 circle.r = 0;//无法访问私有成员,相当于又为circle创建了一个共有成员r
17 alert(circle.getArea());
18 circle.init(0);//通过公有的工具函数便可以访问了。
19 alert(circle.getArea());
20 };
访问:
对于私有成员,直接访问即可,前面不用加任何修饰,
对于公有的访问在单体作用域内前面要加上“this.”,在单体作用域外前面要加上“circle.”(单体名字.)
呵呵,似乎有点味道了!
3.利用分支技术来来封装浏览器之间的差异
注意的地方:
a一定要用闭包,实现即时绑定
b每个分支之间用分号隔开
c最后返回的是分支的名字
d调用的时候用单体名+分支的方法名;
1 // 利用单体的分支技术来定义XHR(XMLHttpRequest)对象,必须要用闭包才可以实现
2 var XHR = (function(){
3 //The three branches
4 var standard = {
5 cXHR:function(){
6 return new XMLHttpRequest();
7 }
8 };
9 var activeXNew = {
10 cXHR:function(){
11 return new ActiveXObject('Msxml2.XMLHttp');
12 }
13 };
14 var activeXOld = {
15 cXHR:function(){
16 return new ActiveXObject('Microsoft.XMLHttp');
17 }
18 };
19 //To assign(分配) the branch, try each method;return whatever doesn't fail
20 var testObject;
21 try{
22 testObject = standard.cXHR();
23 return standard;// return this branch if no error was thrown
24 }catch(e){
25 try{
26 testObject = activeXNew.cXHR();
27 return activeXNew;
28 }catch(e){
29 try{
30 testObject = activeXOld.cXHR();
31 return activeXOld;
32 }catch(e){
33 throw new Error('Create the XMLHttpRequestObject failed!');
34 }
35 }
36 }
37 })();
38 window.onload = function(){
39 alert(XHR.cXHR());
40 }
2 var XHR = (function(){
3 //The three branches
4 var standard = {
5 cXHR:function(){
6 return new XMLHttpRequest();
7 }
8 };
9 var activeXNew = {
10 cXHR:function(){
11 return new ActiveXObject('Msxml2.XMLHttp');
12 }
13 };
14 var activeXOld = {
15 cXHR:function(){
16 return new ActiveXObject('Microsoft.XMLHttp');
17 }
18 };
19 //To assign(分配) the branch, try each method;return whatever doesn't fail
20 var testObject;
21 try{
22 testObject = standard.cXHR();
23 return standard;// return this branch if no error was thrown
24 }catch(e){
25 try{
26 testObject = activeXNew.cXHR();
27 return activeXNew;
28 }catch(e){
29 try{
30 testObject = activeXOld.cXHR();
31 return activeXOld;
32 }catch(e){
33 throw new Error('Create the XMLHttpRequestObject failed!');
34 }
35 }
36 }
37 })();
38 window.onload = function(){
39 alert(XHR.cXHR());
40 }
对于单体据说是最常用的模式之一了,至于利弊嘛要在实践中慢慢的体会了,由于本人也是初学,所以没有太多的发言权,不足指出还忘高手指教