javascript 設(shè)計(jì)模式之單體模式 面向?qū)ο髮W(xué)習(xí)基礎(chǔ)
更新時(shí)間:2010年04月18日 01:09:56 作者:
單體是在腳本加載時(shí)創(chuàng)建的,能將一系列有關(guān)聯(lián)的變量和方法組織為一個(gè)邏輯單元,邏輯單元里面的內(nèi)容通過(guò)單一的變量進(jìn)行訪問(wèn),也是筆記基礎(chǔ)與常用的面向?qū)ο蟮亩x方法。
單體模式(singleton)
單體是在腳本加載時(shí)創(chuàng)建的,能將一系列有關(guān)聯(lián)的變量和方法組織為一個(gè)邏輯單元,邏輯單元里面的內(nèi)容通過(guò)單一的變量進(jìn)行訪問(wèn);
一個(gè)單體主要分為三部分
用于訪問(wèn)內(nèi)部信息的入口變量(如:Sky)
屬性(如:nickName/age/timeInfo)
方法(如:sayHello)
基本結(jié)構(gòu)
var Sky = {
/*
* 作用一,變量管理
*/
nickName: "sky",
age: "26",
/*
* 作用二,加載中初始化變量
* 在加載過(guò)程中執(zhí)行并初始化Sky.info
*/
timeInfo: function()
{
var _year = new Date().getFullYear();
return _year;
}(),
/*
* 作用三,函數(shù)管理,讓你的函數(shù)看起來(lái)不再那么散亂
*/
sayHello: function()
{
alert("hello,world!");
}
}
//所有內(nèi)部信息通過(guò)Sky這個(gè)變量進(jìn)行訪問(wèn);
alert(Sky.timeInfo);
以下是更詳細(xì)的說(shuō)明,看完了這篇文章,相信你應(yīng)該差不多了解了,網(wǎng)上好多高手的js寫(xiě)法了,單體模式很常用。
單體是一個(gè)用來(lái)劃分命名空間并將一批相關(guān)的屬性和方法組織在一起的對(duì)象,如果他可以被實(shí)例化,那么他只能被實(shí)例化一次。
單體模式是javascript里面最基本但也是最有用的模式之一。
特點(diǎn):
. 可以來(lái)劃分命名空間,從而清除全局變量所帶來(lái)的危險(xiǎn)。
. 利用分支技術(shù)來(lái)來(lái)封裝瀏覽器之間的差異。
. 可以把代碼組織的更為一體,便于閱讀和維護(hù)。
單體的基本結(jié)構(gòu)(正確寫(xiě)法):
/*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中對(duì)象成的訪問(wèn)必須是顯示的,即this是不能省略的
},
init:function(w,h){
// width = w;
// height = h;這種方式相當(dāng)于定義了兩個(gè)全局變量,(沒(méi)加var聲明的變量為全局變量)
// 并不是對(duì)對(duì)象width和height的賦值
//下面是正確的
this.width = w;
this.height = h;
}
}//box劃分了一個(gè)命名空間,命名空間里的變量只在空間里有效
上面的單體中的所有的成員以及方法都是公有的(public),也就是在單體的外部可以對(duì)他們進(jìn)行任意的改動(dòng),那為什么說(shuō)單體提供了一個(gè)命名空間呢?
我們繼續(xù):
var box = {
width:0,
height:0,//單體的變量
getArea:function(){
return width*height;//中的,width,height其實(shí)并不是單體的變量,而是在init中定義的全局變量
}
init:function(w,h){
width = w;
height = h;
}
}//init中width,height其實(shí)并不是單體的變量
window.onload = function(){
var init = box.getArea();
alert(init);
}
由于沒(méi)有對(duì)init中的width,height進(jìn)行初始化,所以會(huì)報(bào)錯(cuò),這樣改一下:
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);
}
發(fā)現(xiàn)可以了,由于init和 getArea所用的width和height并不是歸單體所有的變量,而是一個(gè)全局變量,所以我們可以在單體外面進(jìn)行隨意調(diào)用而不受影響
如果我們這樣寫(xiě)一下就更明白了:
var box = {
width:0,
height:0,
getArea:function(){
return width*height;//js中對(duì)象成的訪問(wèn)必須是顯示的,即this是不能省略的
},
init:function(w,h){
width = w;
height = h;
}
}//這里的width,height其實(shí)并不是單體的對(duì)象
window.onload = function(){
width = 0;
height = 0;
var width = box.getArea();
alert(width);
}
這樣寫(xiě)又會(huì)報(bào)錯(cuò)了,可見(jiàn)我們以上的方式對(duì)于全局變量并沒(méi)有建立起一個(gè)命名空間,全局變量為我們帶來(lái)了危險(xiǎn)。所以最上面的寫(xiě)法是對(duì)的,我們來(lái)驗(yàn)證一下:
var box = {
width:2,
height:2,
getArea:function(){
return this.width*this.height;//js中對(duì)象成的訪問(wèn)必須是顯示的,即this是不能省略的
},
init:function(w,h){
this.width = w;
this.height = h;
}
}
window.onload = function(){
width = 0;
height = 0;
var width = box.getArea();
alert(width);
}
可見(jiàn)在window.onload中的width 和height已經(jīng)沒(méi)有干擾了,因?yàn)閱误w為單體中的width和height建立了一個(gè)命名空間。
成員的屬性:
討論完命名空間,我們來(lái)對(duì)單體變量和方法的屬性做一下設(shè)定。學(xué)過(guò)其他語(yǔ)言的人(java,c++,c#...)都應(yīng)該很了解其中類(lèi)成員的public和private,
雖然在javascript中沒(méi)有這么嚴(yán)格的面向?qū)ο?oop),但是我們可以借助閉包來(lái)進(jìn)行一個(gè)模仿,畢竟有的變量設(shè)為public是很不好的。
var circle = (function(){
//pravite member!
var r = 5;
var pi = 3.1416;//后面用分號(hào)
return{//public member
getArea:function(){
return r*r*pi;//訪問(wèn)私有成員不要加this
},//后面用逗號(hào)
//如果想改變r(jià)和pi的值,只能通過(guò)設(shè)置一個(gè)公有的函數(shù)來(lái)實(shí)現(xiàn)
init:function(setR){
r = setR;
}
}
})()
window.onload = function(){
circle.r = 0;//無(wú)法訪問(wèn)私有成員,相當(dāng)于又為circle創(chuàng)建了一個(gè)共有成員r
alert(circle.getArea());
circle.init(0);//通過(guò)公有的工具函數(shù)便可以訪問(wèn)了。
alert(circle.getArea());
};
私有變量、方法是只讀的,公有變量、方法是可讀可寫(xiě)的
訪問(wèn):
對(duì)于私有成員,直接訪問(wèn)即可,前面不用加任何修飾,
對(duì)于公有的訪問(wèn)在單體作用域內(nèi)前面要加上“this.”,在單體作用域外前面要加上“circle.”(單體名字.)
呵呵,似乎有點(diǎn)味道了!
.利用分支技術(shù)來(lái)來(lái)封裝瀏覽器之間的差異
注意的地方:
a一定要用閉包,實(shí)現(xiàn)即時(shí)綁定
b每個(gè)分支之間用分號(hào)隔開(kāi)
c最后返回的是分支的名字
d調(diào)用的時(shí)候用單體名+分支的方法名;
// 利用單體的分支技術(shù)來(lái)定義XHR(XMLHttpRequest)對(duì)象,必須要用閉包才可以實(shí)現(xiàn)
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());
}
最后再啰嗦幾句:
對(duì)于單體據(jù)說(shuō)是最常用的模式之一了,至于利弊嘛要在實(shí)踐中慢慢的體會(huì)了,由于本人也是初學(xué),所以沒(méi)有太多的發(fā)言權(quán),不足指出還忘高手指教
單體是在腳本加載時(shí)創(chuàng)建的,能將一系列有關(guān)聯(lián)的變量和方法組織為一個(gè)邏輯單元,邏輯單元里面的內(nèi)容通過(guò)單一的變量進(jìn)行訪問(wèn);
一個(gè)單體主要分為三部分
用于訪問(wèn)內(nèi)部信息的入口變量(如:Sky)
屬性(如:nickName/age/timeInfo)
方法(如:sayHello)
基本結(jié)構(gòu)
復(fù)制代碼 代碼如下:
var Sky = {
/*
* 作用一,變量管理
*/
nickName: "sky",
age: "26",
/*
* 作用二,加載中初始化變量
* 在加載過(guò)程中執(zhí)行并初始化Sky.info
*/
timeInfo: function()
{
var _year = new Date().getFullYear();
return _year;
}(),
/*
* 作用三,函數(shù)管理,讓你的函數(shù)看起來(lái)不再那么散亂
*/
sayHello: function()
{
alert("hello,world!");
}
}
//所有內(nèi)部信息通過(guò)Sky這個(gè)變量進(jìn)行訪問(wèn);
alert(Sky.timeInfo);
以下是更詳細(xì)的說(shuō)明,看完了這篇文章,相信你應(yīng)該差不多了解了,網(wǎng)上好多高手的js寫(xiě)法了,單體模式很常用。
單體是一個(gè)用來(lái)劃分命名空間并將一批相關(guān)的屬性和方法組織在一起的對(duì)象,如果他可以被實(shí)例化,那么他只能被實(shí)例化一次。
單體模式是javascript里面最基本但也是最有用的模式之一。
特點(diǎn):
. 可以來(lái)劃分命名空間,從而清除全局變量所帶來(lái)的危險(xiǎn)。
. 利用分支技術(shù)來(lái)來(lái)封裝瀏覽器之間的差異。
. 可以把代碼組織的更為一體,便于閱讀和維護(hù)。
單體的基本結(jié)構(gòu)(正確寫(xiě)法):
復(fù)制代碼 代碼如下:
/*Basic Singleton*/
var Singleton = {
attribute1:true,
attribute2:10,
method1:function(){},
method2:function(){}
};
劃分命名空間:
復(fù)制代碼 代碼如下:
var box = {
width:0,
height:0,
getArea:function(){
return this.width*this.height;//js中對(duì)象成的訪問(wèn)必須是顯示的,即this是不能省略的
},
init:function(w,h){
// width = w;
// height = h;這種方式相當(dāng)于定義了兩個(gè)全局變量,(沒(méi)加var聲明的變量為全局變量)
// 并不是對(duì)對(duì)象width和height的賦值
//下面是正確的
this.width = w;
this.height = h;
}
}//box劃分了一個(gè)命名空間,命名空間里的變量只在空間里有效
上面的單體中的所有的成員以及方法都是公有的(public),也就是在單體的外部可以對(duì)他們進(jìn)行任意的改動(dòng),那為什么說(shuō)單體提供了一個(gè)命名空間呢?
我們繼續(xù):
復(fù)制代碼 代碼如下:
var box = {
width:0,
height:0,//單體的變量
getArea:function(){
return width*height;//中的,width,height其實(shí)并不是單體的變量,而是在init中定義的全局變量
}
init:function(w,h){
width = w;
height = h;
}
}//init中width,height其實(shí)并不是單體的變量
window.onload = function(){
var init = box.getArea();
alert(init);
}
由于沒(méi)有對(duì)init中的width,height進(jìn)行初始化,所以會(huì)報(bào)錯(cuò),這樣改一下:
復(fù)制代碼 代碼如下:
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);
}
發(fā)現(xiàn)可以了,由于init和 getArea所用的width和height并不是歸單體所有的變量,而是一個(gè)全局變量,所以我們可以在單體外面進(jìn)行隨意調(diào)用而不受影響
如果我們這樣寫(xiě)一下就更明白了:
復(fù)制代碼 代碼如下:
var box = {
width:0,
height:0,
getArea:function(){
return width*height;//js中對(duì)象成的訪問(wèn)必須是顯示的,即this是不能省略的
},
init:function(w,h){
width = w;
height = h;
}
}//這里的width,height其實(shí)并不是單體的對(duì)象
window.onload = function(){
width = 0;
height = 0;
var width = box.getArea();
alert(width);
}
這樣寫(xiě)又會(huì)報(bào)錯(cuò)了,可見(jiàn)我們以上的方式對(duì)于全局變量并沒(méi)有建立起一個(gè)命名空間,全局變量為我們帶來(lái)了危險(xiǎn)。所以最上面的寫(xiě)法是對(duì)的,我們來(lái)驗(yàn)證一下:
復(fù)制代碼 代碼如下:
var box = {
width:2,
height:2,
getArea:function(){
return this.width*this.height;//js中對(duì)象成的訪問(wèn)必須是顯示的,即this是不能省略的
},
init:function(w,h){
this.width = w;
this.height = h;
}
}
window.onload = function(){
width = 0;
height = 0;
var width = box.getArea();
alert(width);
}
可見(jiàn)在window.onload中的width 和height已經(jīng)沒(méi)有干擾了,因?yàn)閱误w為單體中的width和height建立了一個(gè)命名空間。
成員的屬性:
討論完命名空間,我們來(lái)對(duì)單體變量和方法的屬性做一下設(shè)定。學(xué)過(guò)其他語(yǔ)言的人(java,c++,c#...)都應(yīng)該很了解其中類(lèi)成員的public和private,
雖然在javascript中沒(méi)有這么嚴(yán)格的面向?qū)ο?oop),但是我們可以借助閉包來(lái)進(jìn)行一個(gè)模仿,畢竟有的變量設(shè)為public是很不好的。
復(fù)制代碼 代碼如下:
var circle = (function(){
//pravite member!
var r = 5;
var pi = 3.1416;//后面用分號(hào)
return{//public member
getArea:function(){
return r*r*pi;//訪問(wèn)私有成員不要加this
},//后面用逗號(hào)
//如果想改變r(jià)和pi的值,只能通過(guò)設(shè)置一個(gè)公有的函數(shù)來(lái)實(shí)現(xiàn)
init:function(setR){
r = setR;
}
}
})()
window.onload = function(){
circle.r = 0;//無(wú)法訪問(wèn)私有成員,相當(dāng)于又為circle創(chuàng)建了一個(gè)共有成員r
alert(circle.getArea());
circle.init(0);//通過(guò)公有的工具函數(shù)便可以訪問(wèn)了。
alert(circle.getArea());
};
私有變量、方法是只讀的,公有變量、方法是可讀可寫(xiě)的
訪問(wèn):
對(duì)于私有成員,直接訪問(wèn)即可,前面不用加任何修飾,
對(duì)于公有的訪問(wèn)在單體作用域內(nèi)前面要加上“this.”,在單體作用域外前面要加上“circle.”(單體名字.)
呵呵,似乎有點(diǎn)味道了!
.利用分支技術(shù)來(lái)來(lái)封裝瀏覽器之間的差異
注意的地方:
a一定要用閉包,實(shí)現(xiàn)即時(shí)綁定
b每個(gè)分支之間用分號(hào)隔開(kāi)
c最后返回的是分支的名字
d調(diào)用的時(shí)候用單體名+分支的方法名;
復(fù)制代碼 代碼如下:
// 利用單體的分支技術(shù)來(lái)定義XHR(XMLHttpRequest)對(duì)象,必須要用閉包才可以實(shí)現(xiàn)
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());
}
最后再啰嗦幾句:
對(duì)于單體據(jù)說(shuō)是最常用的模式之一了,至于利弊嘛要在實(shí)踐中慢慢的體會(huì)了,由于本人也是初學(xué),所以沒(méi)有太多的發(fā)言權(quán),不足指出還忘高手指教
您可能感興趣的文章:
- [js高手之路]設(shè)計(jì)模式系列課程-發(fā)布者,訂閱者重構(gòu)購(gòu)物車(chē)的實(shí)例
- JS模式之簡(jiǎn)單的訂閱者和發(fā)布者模式完整實(shí)例
- JavaScript設(shè)計(jì)模式之觀察者模式(發(fā)布者-訂閱者模式)
- JavaScript 設(shè)計(jì)模式 安全沙箱模式
- 學(xué)習(xí)JavaScript設(shè)計(jì)模式(鏈?zhǔn)秸{(diào)用)
- javascript設(shè)計(jì)模式之解釋器模式詳解
- NodeJS設(shè)計(jì)模式總結(jié)【單例模式,適配器模式,裝飾模式,觀察者模式】
- JavaScript設(shè)計(jì)模式之工廠方法模式介紹
- 大型JavaScript應(yīng)用程序架構(gòu)設(shè)計(jì)模式
- 原生js實(shí)現(xiàn)的觀察者和訂閱者模式簡(jiǎn)單示例
相關(guān)文章
手把手教你自己寫(xiě)一個(gè)js表單驗(yàn)證框架的方法
其實(shí)我自己也就能簡(jiǎn)單用用js而已,但是呢,相對(duì)很多初學(xué)者來(lái)說(shuō)多懂了點(diǎn)Know How所以斗膽孟浪一下,將一些所得記錄下來(lái),以供更多的初學(xué)者能夠知道一個(gè)東西的實(shí)現(xiàn)過(guò)程,省去在源碼里摸索的過(guò)程。2010-09-09JavaScript面象對(duì)象設(shè)計(jì)
學(xué)習(xí)js的高境界就是使用面向?qū)ο蟮姆椒?,?shí)現(xiàn)js的調(diào)用2008-04-04學(xué)習(xí)JS面向?qū)ο蟪晒?借國(guó)慶發(fā)布個(gè)最新作品與大家交流
學(xué)習(xí)JS面向?qū)ο蟪晒?,借?guó)慶發(fā)布個(gè)最新作品與大家交流,大家可以看下。2009-10-10javascript 面向?qū)ο缶幊?function也是類(lèi)
function在javascript中用來(lái)創(chuàng)建函數(shù)或方法,但要想實(shí)現(xiàn)面向?qū)ο蠓绞降木幊?,?lèi)是不可或缺的角色之一,而且是主角。2009-09-09Riot.js 快速的JavaScript單元測(cè)試框架
Riot是一個(gè)快速,富有表現(xiàn)力,上下文驅(qū)動(dòng) 的單元測(cè)試框架。最初是用于Ruby的單元測(cè)試,最近作者Alex Young又實(shí)現(xiàn)了Riot的JavaScript版- Riot.js。2009-11-11面向?qū)ο蟮腏avascript之二(接口實(shí)現(xiàn)介紹)
接口是面向?qū)ο驤avascript工具箱中最有用的特性之一。我們都知道GOF在設(shè)計(jì)模式中說(shuō)到:面向接口編程,而非面向?qū)崿F(xiàn)編程2012-01-01