可能影響你一生的js寫法之單例模式>淠(看完后沉思...)

《parctical common lisp》的作者曾說,如果你需要一種模式棒假,那一定是哪里出了問題溯职。他所說的問題是指因為語言的天生缺陷,不得不去尋求和總結(jié)一種通用的解決方案帽哑。

不管是弱類型或強類型谜酒,靜態(tài)或動態(tài)語言,命令式或說明式語言妻枕、每種語言都有天生的優(yōu)缺點僻族。一個牙買加運動員, 在短跑甚至拳擊方面有一些優(yōu)勢屡谐,在練瑜伽上就欠缺一些述么。

術(shù)士和暗影牧師很容易成為一個出色的輔助,而一個背著梅肯滿地圖飛的敵法就會略顯尷尬愕掏。 換到程序中, 靜態(tài)語言里可能需要花很多功夫來實現(xiàn)裝飾者度秘,而js由于能隨時往對象上面扔方法,以至于裝飾者模式在js里成了雞肋饵撑。

講javascript設(shè)計模式的書還比較少. Pro javaScript Design Patterns.是比較經(jīng)典的一本剑梳,但是它里面的例子舉得比較啰嗦,所以結(jié)合我在工作中寫過的代碼肄梨,把我的理解總結(jié)一下阻荒。如果我的理解出現(xiàn)了偏差,請不吝指正众羡。

單例模式

單例模式的定義是產(chǎn)生一個類的唯一實例侨赡,但js本身是一種“無類”語言。很多講js設(shè)計模式的文章把{}當成一個單例來使用也勉強說得通。因為js生成對象的方式有很多種羊壹,我們來看下另一種更有意義的單例蓖宦。
有這樣一個常見的需求,點擊某個按鈕的時候需要在頁面彈出一個遮罩層油猫。比如web.qq.com點擊登錄的時候.

這個生成灰色背景遮罩層的代碼是很好寫的.

var createMask = function(){
 
   return document.body.appendChild(  document.createElement(div)  );
 
}

$( 'button' ).click( function(){
 
   Var mask  = createMask();
 
   mask.show();
 
})

問題是, 這個遮罩層是全局唯一的, 那么每次調(diào)用createMask都會創(chuàng)建一個新的div, 雖然可以在隱藏遮罩層的把它remove掉. 但顯然這樣做不合理.
再看下第二種方案, 在頁面的一開始就創(chuàng)建好這個div. 然后用一個變量引用它.

var mask = document.body.appendChild( document.createElement( ''div' ) );
 
$( 'button' ).click( function(){
 
   mask.show();
 
} )

這樣確實在頁面只會創(chuàng)建一個遮罩層div, 但是另外一個問題隨之而來, 也許我們永遠都不需要這個遮罩層, 那又浪費掉一個div, 對dom節(jié)點的任何操作都應(yīng)該非常吝嗇.
如果可以借助一個變量. 來判斷是否已經(jīng)創(chuàng)建過div呢?

var mask;
 
var createMask = function(){
 
if ( mask ) return mask;
 
else{
 
mask = document,body.appendChild(  document.createElement(div)  );
 
return mask;
 
}
 
}

看起來不錯, 到這里的確完成了一個產(chǎn)生單列對象的函數(shù). 我們再仔細看這段代碼有什么不妥.
首先這個函數(shù)是存在一定副作用的, 函數(shù)體內(nèi)改變了外界變量mask的引用, 在多人協(xié)作的項目中, createMask是個不安全的函數(shù). 另一方面, mask這個全局變量并不是非需不可. 再來改進一下.

var createMask = function(){
  var mask;
  return function(){
       return mask || ( mask = document.body.appendChild( document.createElement('div') ) )
  }
}()

用了個簡單的閉包把變量mask包起來, 至少對于createMask函數(shù)來講, 它是封閉的.
可能看到這里, 會覺得單例模式也太簡單了. 的確一些設(shè)計模式都是非常簡單的, 即使從沒關(guān)注過設(shè)計模式的概念, 在平時的代碼中也不知不覺用到了一些設(shè)計模式. 就像多年前我明白老漢推車是什么回事的時候也想過尼瑪原來這就是老漢推車.
GOF里的23種設(shè)計模式, 也是在軟件開發(fā)中早就存在并反復使用的模式. 如果程序員沒有明確意識到他使用過某些模式, 那么下次他也許會錯過更合適的設(shè)計 (這段話來自《松本行弘的程序世界》).
再回來正題, 前面那個單例還是有缺點. 它只能用于創(chuàng)建遮罩層. 假如我又需要寫一個函數(shù), 用來創(chuàng)建一個唯一的xhr對象呢? 能不能找到一個通用的singleton包裝器.
js中函數(shù)是第一型, 意味著函數(shù)也可以當參數(shù)傳遞. 看看最終的代碼.

var singleton = function( fn ){
    var result;
    return function(){
        return result || ( result = fn .apply( this, arguments ) );
    }
}
 
var createMask = singleton( function(){
 
return document.body.appendChild( document.createElement('div') );
 
 })

用一個變量來保存第一次的返回值, 如果它已經(jīng)被賦值過, 那么在以后的調(diào)用中優(yōu)先返回該變量. 而真正創(chuàng)建遮罩層的代碼是通過回調(diào)函數(shù)的方式傳人到singleton包裝器中的. 這種方式其實叫橋接模式. 關(guān)于橋接模式, 放在后面一點點來說.
然而singleton函數(shù)也不是完美的, 它始終還是需要一個變量result來寄存div的引用. 遺憾的是js的函數(shù)式特性還不足以完全的消除聲明和語句.

轉(zhuǎn)載自AlloyTeam:http://www.alloyteam.com/2012/10/common-javascript-design-patterns/

————
前端·小d

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末稠茂,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子情妖,更是在濱河造成了極大的恐慌睬关,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,865評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件毡证,死亡現(xiàn)場離奇詭異电爹,居然都是意外死亡,警方通過查閱死者的電腦和手機料睛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,296評論 3 399
  • 文/潘曉璐 我一進店門丐箩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人恤煞,你說我怎么就攤上這事屎勘。” “怎么了居扒?”我有些...
    開封第一講書人閱讀 169,631評論 0 364
  • 文/不壞的土叔 我叫張陵概漱,是天一觀的道長。 經(jīng)常有香客問我喜喂,道長犀概,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,199評論 1 300
  • 正文 為了忘掉前任夜惭,我火速辦了婚禮,結(jié)果婚禮上铛绰,老公的妹妹穿的比我還像新娘诈茧。我一直安慰自己,他們只是感情好捂掰,可當我...
    茶點故事閱讀 69,196評論 6 398
  • 文/花漫 我一把揭開白布敢会。 她就那樣靜靜地躺著,像睡著了一般这嚣。 火紅的嫁衣襯著肌膚如雪鸥昏。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,793評論 1 314
  • 那天姐帚,我揣著相機與錄音吏垮,去河邊找鬼。 笑死,一個胖子當著我的面吹牛膳汪,可吹牛的內(nèi)容都是我干的唯蝶。 我是一名探鬼主播,決...
    沈念sama閱讀 41,221評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼遗嗽,長吁一口氣:“原來是場噩夢啊……” “哼粘我!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起痹换,我...
    開封第一講書人閱讀 40,174評論 0 277
  • 序言:老撾萬榮一對情侶失蹤征字,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后娇豫,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體匙姜,經(jīng)...
    沈念sama閱讀 46,699評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,770評論 3 343
  • 正文 我和宋清朗相戀三年锤躁,在試婚紗的時候發(fā)現(xiàn)自己被綠了搁料。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,918評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡系羞,死狀恐怖郭计,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情椒振,我是刑警寧澤昭伸,帶...
    沈念sama閱讀 36,573評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站澎迎,受9級特大地震影響庐杨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜夹供,卻給世界環(huán)境...
    茶點故事閱讀 42,255評論 3 336
  • 文/蒙蒙 一灵份、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧哮洽,春花似錦填渠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,749評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至匪凉,卻和暖如春枪眉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背再层。 一陣腳步聲響...
    開封第一講書人閱讀 33,862評論 1 274
  • 我被黑心中介騙來泰國打工贸铜, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留堡纬,地道東北人。 一個月前我還...
    沈念sama閱讀 49,364評論 3 379
  • 正文 我出身青樓萨脑,卻偏偏與公主長得像隐轩,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子渤早,可洞房花燭夜當晚...
    茶點故事閱讀 45,926評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 1.幾種基本數(shù)據(jù)類型?復雜數(shù)據(jù)類型?值類型和引用數(shù)據(jù)類型?堆棧數(shù)據(jù)結(jié)構(gòu)? 基本數(shù)據(jù)類型:Undefined职车、Nul...
    極樂君閱讀 5,527評論 0 106
  • 工廠模式類似于現(xiàn)實生活中的工廠可以產(chǎn)生大量相似的商品,去做同樣的事情鹊杖,實現(xiàn)同樣的效果;這時候需要使用工廠模式悴灵。簡單...
    舟漁行舟閱讀 7,781評論 2 17
  • 轉(zhuǎn)載的正文 地址--理解java接口回調(diào)機制
    口袋易佰閱讀 181評論 0 1
  • 520這天积瞒,我最想講的故事 好友秋今日大婚。昨晚放言說要用酒撂倒我登下,我不自量力地吹起了牛皮:“我可是從來滴酒不沾茫孔,...
    Bevon英語翻譯閱讀 227評論 0 0
  • xx233閱讀 105評論 0 0