摘要:使用構(gòu)造函數(shù)如果被實例化過,就返回實例化的結(jié)果這種方式比較簡潔,通過判斷是否已經(jīng)實例化過,但是也沒啥安全性,如果在外部修改那很可能單例模式就被破壞了。
摘要
單體模式也有人稱為單例模式,是javaScript 中最基本但又最有用的模式之一。
什么是單體一講到概念第一反應(yīng)就是WTF
其實單體模式是最常用,也是最有用的一種模式。而我們也會在項目中不知不覺的寫一些單體模式,只是我們沒有意識到,這也是一種設(shè)計模式??匆粋€簡單的例子:
var zoom = { bird: 10, monkey: 10, play: function() {}, eat: function() {} }
這和我隨手找的一個對象有什么區(qū)別,從嚴(yán)格意義上講這確實不能稱為一個單體。但我們可以分析一下這個對象,其中有兩個zoom相關(guān)的屬性,和兩個zoom相關(guān)的方法。實際上最簡單的單體就是字面量,它是把一些有一定關(guān)系的方法和屬性組織在一起。
但他違背了面向?qū)ο笤O(shè)計的一條原則:類可以被擴展,但不應(yīng)該被修改。聽到這里我們也不需要慌,因為(Python,Ruby)都允許在定義了類之后對其修改。
可能你還是不知道單體與普通字面量有什么不同,那就再看一個例子:
var zoom = function() { var bird = 10; var monkey = 10; this.play = function() {} this.eat = function() {} } var zoom1 = new zoom(); var zoom2 = new zoom(); console.log(zoom1 === zoom2)//false;
zoom被實例化兩次,但兩個實例明顯不相等。因為zoom1,zoom2的指針,并沒有只向內(nèi)存中的同一地址。這也正好可以引出單體與不同字面量的不同。按傳統(tǒng)定義,單體是一個只能被實例化一次,并且可以通過一個眾所周知的訪問點訪問的對象。后半句簡單說,就是可以全局訪問。
總結(jié)一下上面內(nèi)容。單體是一個用來劃分命名空間并將一批相關(guān)方法和屬性組織在一起的對象,如果它可以被實例化,那么它只能被實例化一次。
與命名空間的關(guān)系如果我們的變量都定義在全局中,一不小心別人重新用相同的變量名,定義一個變量,那我們的代碼就會出問題,而且這種問題很難排查。為了避免這種不確定性,我們可以把代碼組織在命名空間中(其實,就是另一個對象中,但這個對象,更具有包含性)
var ZoomSpace = { otherFunction: function() {} } ZoomSpace.zoomUtil = { bird: 10, monkey: 10, play: function() {}, eat: function() {} }
這樣如果在全局中重定義了zoomUtil,我們的zoomUtil也不會受到影響。
使用構(gòu)造函數(shù)function zoomUtil() { //如果被實例化過,就返回實例化的結(jié)果 if(zoomUtil.unique !== undefined) { return zoomUtil.unique; } var bird = 10; var monkey = 10; function play() {}; function eat(){}; return zoomUtil.unique = this; } var zoom1 = new zoomUtil(); var zoom2 = new zoomUtil(); console.log(zoom1 === zoom2)//true
這種方式比較簡潔,通過判斷是否已經(jīng)實例化過,但是也沒啥安全性,如果在外部修改zoomUtil.unique 那很可能單例模式就被破壞了。
擁有私有成員的單體 使用下劃線表示下劃線表示私有成員,是約定俗稱的一種方法,告訴別人不要直接訪問私有方法。
使用上面我們已經(jīng)定義好的命名空間:
ZoomSpace.zoomUtil = { bird: 10, monkey: 10, _runTime: function() { return ++this.bird; }, play: function() { //return this._runTime(); 盡量不要再共有方法中使用this //this很可能因為此方法使用在別的函數(shù)中導(dǎo)致指向window return ZoomSpace.zoomUtil._runTime(); }, eat: function() {} } console.log(ZoomSpace.zoomUtil.play());//11
這種方法的安全性也不好,主要靠人為的約束,但是如果有人非要用我們的私有方法,導(dǎo)致我們刪除或者修改私有方法后,他的程序不能用,只能能跟他說no zuo no die。
使用閉包之前我們的單體都是這樣的:
ZoomSpace.zoomUitl = {};
現(xiàn)在我們用一個立即執(zhí)行的函數(shù)創(chuàng)建,像這樣:
ZoomSpace.zoomUitl = (function(){ return {}; })();
以往的做法是把變量和函數(shù)定義在構(gòu)造函數(shù)內(nèi)部。因此,每次生成一個實例,所有的方法屬性都會被再次創(chuàng)建。這樣的做法很低效。而現(xiàn)在的做法我們不必要擔(dān)心定義的屬性過多,因為它只會被實例化一次。我們來改寫上面的例子:
ZoomSpace.zoomUtil = (function(){ //私有屬性和方法 var bird = 10; var monkey = 10; function runTime(){ return ++bird;//不需要使用this }; function otherFunction(){}; return { play:function(){ return runTime(); } } })() console.log(ZoomSpace.zoomUtil.play());//11
如果你想通過new的方式來寫,可以像下面這樣修改:
var ZoomSpace = {}; ZoomSpace.zoomUtil = (function() { //私有屬性和方法 var unique; //唯一值 function zoomUtilConstructor() { // 是否被實例化過 if(unique.constructor === zoomUtilConstructor) { //如果實例化過,返回已經(jīng)實例化的對象 return unique; } var bird = 10; var monkey = 10; function runTime() { return ++bird; }; this.play = function(){ return runTime(); } // 保存實例化的對象 return unique = this; } // 保存構(gòu)造函數(shù) return unique = zoomUtilConstructor; })() var zoom1 = new ZoomSpace.zoomUtil(); var zoom2 = new ZoomSpace.zoomUtil(); console.log(zoom1 === zoom2); //true
方法有很多,具體看那種最適合。
總結(jié)考慮否嚴(yán)格的只需要一個實例對象的類,那么就要考慮使用單體模式。使用數(shù)據(jù)緩存來存儲該單例,用作判斷單例是否已經(jīng)生成,是單例模式主要的實現(xiàn)思路。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/87296.html
摘要:單體模式在多種設(shè)計模式中,單體模式是最簡單,也是最基礎(chǔ)的設(shè)計模式。和之前說到的下劃線表示私用成員方法比較起來,最大的優(yōu)點就是可以創(chuàng)建真正的私用成員,使其不會在構(gòu)造函數(shù)之外被隨意修改。 單體模式 在多種Javascript設(shè)計模式中,單體模式是最簡單,也是最基礎(chǔ)的設(shè)計模式。它基礎(chǔ)到似乎不太像是一種設(shè)計模式,因為我們在編寫代碼的過程中隨時都會用到,并不需要過多思考,這是它簡單的一面。同時...
摘要:微服務(wù)常用的進程間通信技術(shù)即表述性狀態(tài)傳遞英文,簡稱是博士在年他的博士論文中提出來的一種軟件架構(gòu)風(fēng)格。摘自微服務(wù)實戰(zhàn)從架構(gòu)到部署處理部分請求失敗對于分布式的微服務(wù),必須要面對的一大問題就是局部請求失敗的處理。 先拋出幾個問題 微服務(wù)架構(gòu)的交互模式有哪些? 微服務(wù)常用的進程間通信技術(shù)有哪些? 如何處理部分請求失敗? API的定義需要注意的事項有哪些 微服務(wù)的通信機制與SOA的通信機制之...
摘要:設(shè)計模式是一套可復(fù)用的,被眾人知曉,經(jīng)過編目分明的,經(jīng)驗的總結(jié)。創(chuàng)建類安全工廠判斷是否調(diào)用關(guān)鍵字設(shè)計模式設(shè)計模式運算符可以用來判斷某個構(gòu)造函數(shù)的屬性所指向的對象是否存在于另外一個要檢測對象的原型鏈上。 設(shè)計模式 是一套可復(fù)用的,被眾人知曉,經(jīng)過編目分明的,經(jīng)驗的總結(jié)。作用:使用設(shè)計模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性 模式類型 創(chuàng)建型設(shè)計模式:解決對象在創(chuàng)建時產(chǎn)...
摘要:單體模式有以下優(yōu)點用來劃分命名空間,減少全局變量數(shù)量。通常我們使用操作符創(chuàng)建單體模式的三種選擇,讓構(gòu)造函數(shù)總返回最初的對象使用全局對象來存儲該實例不推薦,容易全局污染。實現(xiàn)該工廠模式并不困難,主要是要找到能夠穿件所需類型對象的構(gòu)造函數(shù)。 介紹 最近開始給自己每周訂個學(xué)習(xí)任務(wù),學(xué)習(xí)結(jié)果反饋為一篇文章的輸出,做好學(xué)習(xí)記錄。 這一周(02.25-03.03)我定的目標(biāo)是《JavaScri...
摘要:注意事項聲明函數(shù)時候處理業(yè)務(wù)邏輯區(qū)分和單例的區(qū)別,配合單例實現(xiàn)初始化構(gòu)造函數(shù)大寫字母開頭推薦注意的成本。簡單工廠模式使用一個類通常為單體來生成實例。 @(書籍閱讀)[JavaScript, 設(shè)計模式] 常見設(shè)計模式 一直對設(shè)計模式不太懂,花了一下午加一晚上的時間,好好的看了看各種設(shè)計模式,并總結(jié)了一下。 設(shè)計模式簡介 設(shè)計模式概念解讀 設(shè)計模式的發(fā)展與在JavaScript中的應(yīng)用 ...
閱讀 1325·2021-11-24 10:24
閱讀 4171·2021-11-22 15:29
閱讀 1103·2019-08-30 15:53
閱讀 2804·2019-08-30 10:54
閱讀 1990·2019-08-29 17:26
閱讀 1297·2019-08-29 17:08
閱讀 616·2019-08-28 17:55
閱讀 1595·2019-08-26 14:01