javascript 设计模式之单体模式 面向对象学习基础


Posted in Javascript onApril 18, 2010

单体模式(singleton)

单体是在脚本加载时创建的,能将一系列有关联的变量和方法组织为一个逻辑单元,逻辑单元里面的内容通过单一的变量进行访问;

一个单体主要分为三部分

用于访问内部信息的入口变量(如:Sky)
属性(如:nickName/age/timeInfo)
方法(如:sayHello)

基本结构

var Sky = { /* 
* 作用一,变量管理 
*/ 
nickName: "sky", 
age: "26", 
/* 
* 作用二,加载中初始化变量 
* 在加载过程中执行并初始化Sky.info 
*/ 
timeInfo: function() 
    { 
var _year = new Date().getFullYear(); 
return _year; 
}(), 
/* 
* 作用三,函数管理,让你的函数看起来不再那么散乱 
*/ 
sayHello: function() 
    { 
alert("hello,world!"); 
} 
} 
//所有内部信息通过Sky这个变量进行访问; 
alert(Sky.timeInfo);

以下是更详细的说明,看完了这篇文章,相信你应该差不多了解了,网上好多高手的js写法了,单体模式很常用。

单体是一个用来划分命名空间并将一批相关的属性和方法组织在一起的对象,如果他可以被实例化,那么他只能被实例化一次。
单体模式是javascript里面最基本但也是最有用的模式之一。
特点:

. 可以来划分命名空间,从而清除全局变量所带来的危险。
. 利用分支技术来来封装浏览器之间的差异。
. 可以把代码组织的更为一体,便于阅读和维护。

单体的基本结构(正确写法):

/*Basic Singleton*/ 
var Singleton = { 
attribute1:true, 
attribute2:10, 
method1:function(){}, 

 method2:function(){} 
};

划分命名空间:
var box = { 
width:0, 
height:0, 
getArea:function(){ 
return this.width*this.height;//js中对象成的访问必须是显示的,即this是不能省略的 
}, 
init:function(w,h){ 
// width = w; 
// height = h;这种方式相当于定义了两个全局变量,(没加var声明的变量为全局变量) 
// 并不是对对象width和height的赋值 
//下面是正确的 
this.width = w; 
this.height = h; 
} 
}//box划分了一个命名空间,命名空间里的变量只在空间里有效

上面的单体中的所有的成员以及方法都是公有的(public),也就是在单体的外部可以对他们进行任意的改动,那为什么说单体提供了一个命名空间呢?

我们继续:

var box = { 
width:0, 
height:0,//单体的变量 
getArea:function(){ 
return width*height;//中的,width,height其实并不是单体的变量,而是在init中定义的全局变量 
} 
init:function(w,h){ 
width = w; 
height = h; 
} 
}//init中width,height其实并不是单体的变量 
window.onload = function(){ 
var init = box.getArea(); 
alert(init); 
}

由于没有对init中的width,height进行初始化,所以会报错,这样改一下:
var box = { 
width:0, 
height:0, 
getArea:function(){ 
return width*height; 
}, 
init:function(w,h){ 
width = w; 
height = h; 
} 
} 
window.onload = function(){ 
width = 0; 
height = 0; 
//or box.init(0,0); 
var init = box.getArea(); 
alert(init); 
}

发现可以了,由于init和 getArea所用的width和height并不是归单体所有的变量,而是一个全局变量,所以我们可以在单体外面进行随意调用而不受影响

如果我们这样写一下就更明白了:

var box = { 
width:0, 
height:0, 
getArea:function(){ 
return width*height;//js中对象成的访问必须是显示的,即this是不能省略的 
}, 
init:function(w,h){ 
width = w; 
height = h; 
} 
}//这里的width,height其实并不是单体的对象 
window.onload = function(){ 
width = 0; 
height = 0; 
var width = box.getArea(); 
alert(width); 
}

这样写又会报错了,可见我们以上的方式对于全局变量并没有建立起一个命名空间,全局变量为我们带来了危险。所以最上面的写法是对的,我们来验证一下:
var box = { 
width:2, 
height:2, 
getArea:function(){ 
return this.width*this.height;//js中对象成的访问必须是显示的,即this是不能省略的 
}, 
init:function(w,h){ 
this.width = w; 
this.height = h; 
} 
} 
window.onload = function(){ 
width = 0; 
height = 0; 
var width = box.getArea(); 
alert(width); 
}

可见在window.onload中的width 和height已经没有干扰了,因为单体为单体中的width和height建立了一个命名空间。

成员的属性:

讨论完命名空间,我们来对单体变量和方法的属性做一下设定。学过其他语言的人(java,c++,c#...)都应该很了解其中类成员的public和private,
虽然在javascript中没有这么严格的面向对象(oop),但是我们可以借助闭包来进行一个模仿,毕竟有的变量设为public是很不好的。

var circle = (function(){ 
//pravite member! 
var r = 5; 
var pi = 3.1416;//后面用分号 
return{//public member 
getArea:function(){ 
return r*r*pi;//访问私有成员不要加this 
},//后面用逗号 
//如果想改变r和pi的值,只能通过设置一个公有的函数来实现 
init:function(setR){ 
r = setR; 
} 
} 
})() 
window.onload = function(){ 
circle.r = 0;//无法访问私有成员,相当于又为circle创建了一个共有成员r 
alert(circle.getArea()); 
circle.init(0);//通过公有的工具函数便可以访问了。 
alert(circle.getArea()); 
};

私有变量、方法是只读的,公有变量、方法是可读可写的
访问:
对于私有成员,直接访问即可,前面不用加任何修饰,
对于公有的访问在单体作用域内前面要加上“this.”,在单体作用域外前面要加上“circle.”(单体名字.)

呵呵,似乎有点味道了!
.利用分支技术来来封装浏览器之间的差异
注意的地方:
a一定要用闭包,实现即时绑定
b每个分支之间用分号隔开
c最后返回的是分支的名字
d调用的时候用单体名+分支的方法名;

// 利用单体的分支技术来定义XHR(XMLHttpRequest)对象,必须要用闭包才可以实现 
var XHR = (function(){ 
//The three branches 
var standard = { 
cXHR:function(){ 
return new XMLHttpRequest(); 
} 
}; 
var activeXNew = { 
cXHR:function(){ 
return new ActiveXObject('Msxml2.XMLHttp'); 
} 
}; 
var activeXOld = { 
cXHR:function(){ 
return new ActiveXObject('Microsoft.XMLHttp'); 
} 
}; 
//To assign(分配) the branch, try each method;return whatever doesn't fail 
var testObject; 
try{ 
testObject = standard.cXHR(); 
return standard;// return this branch if no error was thrown 
}catch(e){ 
try{ 
testObject = activeXNew.cXHR(); 
return activeXNew; 
}catch(e){ 
try{ 
testObject = activeXOld.cXHR(); 
return activeXOld; 
}catch(e){ 
throw new Error('Create the XMLHttpRequestObject failed!'); 
} 
} 
} 
})(); 
window.onload = function(){ 
alert(XHR.cXHR()); 
}

最后再??录妇洌
对于单体据说是最常用的模式之一了,至于利弊嘛要在实践中慢慢的体会了,由于本人也是初学,所以没有太多的发言权,不足指出还忘高手指教
Javascript 相关文章推荐
javascript编程起步(第五课)
Jan 10 Javascript
改写一个简单的菜单 弹性大小
Dec 02 Javascript
javaScript 利用闭包模拟对象的私有属性
Dec 29 Javascript
使用jquery写个更改表格行顺序的小功能
Apr 29 Javascript
javascript中声明函数的方法及调用函数的返回值
Jul 22 Javascript
Javascript实现的Map集合工具类完整实例
Jul 31 Javascript
jQuery通过写入cookie实现更换网页背景的方法
Apr 15 Javascript
vuejs手把手教你写一个完整的购物车实例代码
Jul 06 Javascript
详解在Vue中如何使用axios跨域访问数据
Jul 07 Javascript
js传递数组参数到后台controller的方法
Mar 29 Javascript
微信小程序之裁剪图片成圆形的实现代码
Oct 11 Javascript
node命令行工具之实现项目工程自动初始化的标准流程
Aug 12 Javascript
js 获取子节点函数 (兼容FF与IE)
Apr 18 #Javascript
几个比较实用的JavaScript 测试及效验工具
Apr 18 #Javascript
javascript JSON操作入门实例
Apr 16 #Javascript
javascript对象之内置对象Math使用方法
Apr 16 #Javascript
jQuery 类twitter的文本字数限制带提示效果插件
Apr 16 #Javascript
jQuery maxlength文本字数限制插件
Apr 16 #Javascript
一款js和css代码压缩工具[附JAVA环境配置方法]
Apr 16 #Javascript
You might like
PHP 危险函数解释 分析
2009/04/22 PHP
一步一步学习PHP(8) php 数组
2010/03/05 PHP
php使用PDO方法详解
2014/12/27 PHP
php获取本周开始日期和结束日期的方法
2015/03/09 PHP
如何解决PHP无法实现多线程的问题
2015/09/25 PHP
PHP开发实现快递查询功能详解
2019/04/08 PHP
YII框架行为behaviors用法示例
2019/04/26 PHP
Laravel框架创建路由的方法详解
2019/09/04 PHP
laravel 如何实现引入自己的函数或类库
2019/10/15 PHP
广告代码静态化js通用函数
2007/05/09 Javascript
JQuery 学习笔记 选择器之二
2009/07/23 Javascript
兼容IE和FF的js脚本代码小结(比较常用)
2010/12/06 Javascript
EXTjs4.0的store的findRecord的BUG演示代码
2013/06/08 Javascript
Javascript实现真实字符串剩余字数提示的实例代码
2013/10/22 Javascript
javascript里绝对用的上的字符分割函数总结
2014/07/31 Javascript
html文档中的location对象属性理解及常见的用法
2014/08/13 Javascript
jquery实现带渐变淡入淡出并向右依次展开的多级菜单效果实例
2015/08/22 Javascript
js时间戳和c#时间戳互转方法(推荐)
2017/02/15 Javascript
深入理解nodejs中Express的中间件
2017/05/19 NodeJs
详解vue-router2.0动态路由获取参数
2017/06/14 Javascript
jQuery实现的form转json经典示例
2017/10/10 jQuery
vue项目中引入noVNC远程桌面的方法
2018/03/05 Javascript
vue与vue-i18n结合实现后台数据的多语言切换方法
2018/03/08 Javascript
JS+HTML实现的圆形可点击区域示例【3种方法】
2018/08/01 Javascript
JS继承定义与使用方法简单示例
2020/02/19 Javascript
微信小程序学习总结(四)事件与冒泡实例分析
2020/06/04 Javascript
vue render函数动态加载img的src路径操作
2020/10/26 Javascript
进一步探究Python的装饰器的运用
2015/05/05 Python
通过实例简单了解Python中yield的作用
2019/12/11 Python
python序列类型种类详解
2020/02/26 Python
python UDF 实现对csv批量md5加密操作
2021/01/01 Python
付款委托书范本
2014/10/05 职场文书
医院党的群众路线教育实践活动学习心得体会
2014/10/30 职场文书
2015年评职称个人工作总结
2015/10/15 职场文书
python 对图片进行简单的处理
2021/06/23 Python
24年收藏2000多部退役军用电台
2022/02/18 无线电