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 相关文章推荐
本地图片预览(支持IE6/IE7/IE8/Firefox3)经验总结
Mar 25 Javascript
JS代码判断IE6,IE7,IE8,IE9的函数代码
Aug 02 Javascript
JavaScript设计模式之单件模式介绍
Dec 28 Javascript
jquery移动节点实例
Jan 14 Javascript
JavaScript获取当前网页最后修改时间的方法
Apr 03 Javascript
jQuery+html5实现div弹出层并遮罩背景
Apr 15 Javascript
JavaScript过滤字符串中的中文与空格方法汇总
Mar 07 Javascript
jQuery Ajax 全局调用封装实例代码详解
Jun 02 Javascript
原生js验证简洁注册登录页面
Dec 17 Javascript
基于Node.js的WebSocket通信实现
Mar 11 Javascript
实现图片首尾平滑轮播(JS原生方法—节流)
Oct 17 Javascript
JS实现点击li标签弹出对应的索引功能【案例】
Feb 18 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 Token(令牌)设计
2008/03/15 PHP
php用正则表达式匹配中文实例详解
2013/11/06 PHP
php实现改变图片直接打开为下载的方法
2015/04/14 PHP
WordPress特定文章对搜索引擎隐藏或只允许搜索引擎查看
2015/12/31 PHP
phpmyadmin下载、安装、配置教程
2017/05/16 PHP
用PHP去掉文件头的Unicode签名(BOM)方法
2017/06/22 PHP
开发跨浏览器javascript常见注意事项
2009/01/01 Javascript
Javascript 遍历对象中的子对象
2009/07/03 Javascript
js 动态加载事件的几种方法总结
2013/12/25 Javascript
详谈JavaScript 匿名函数及闭包
2014/11/14 Javascript
js实现非常简单的焦点图切换特效实例
2015/05/07 Javascript
javascript文本模板用法实例
2015/07/31 Javascript
jQuery Select下拉框操作小结(推荐)
2016/07/22 Javascript
AngularJS封装指令方法详解
2016/12/12 Javascript
jquery事件与绑定事件
2017/03/16 Javascript
详解angularjs的数组传参方式的简单实现
2017/07/28 Javascript
简单实现jQuery手风琴效果
2017/08/18 jQuery
微信小程序-getUserInfo回调的实例详解
2017/10/27 Javascript
vue2.0实现前端星星评分功能组件实例代码
2018/02/12 Javascript
vue项目中mock.js的使用及基本用法
2019/05/22 Javascript
使用Node.js实现base64和png文件相互转换的方法
2020/03/11 Javascript
js实现弹窗猜数字游戏
2020/11/26 Javascript
vue项目中openlayers绘制行政区划
2020/12/24 Vue.js
[03:04]2018年国际邀请赛典藏宝瓶&莱恩声望物品展示 片尾有彩蛋
2018/06/04 DOTA
可用于监控 mysql Master Slave 状态的python代码
2013/02/10 Python
python中的多重继承实例讲解
2014/09/28 Python
大学生毕业求职找工作的自我评价
2013/09/29 职场文书
超市采购员岗位职责
2014/02/01 职场文书
个人实习生的自我评价
2014/02/16 职场文书
2014年秋季开学寄语
2014/08/02 职场文书
三八妇女节趣味活动方案
2014/08/23 职场文书
2014年绿化工作总结
2014/12/09 职场文书
事业单位年度考核评语
2014/12/31 职场文书
2015年妇委会工作总结
2015/05/22 职场文书
小学五年级班主任工作经验交流材料
2015/11/02 职场文书
Go语言中的UTF-8实现
2021/04/26 Golang