摘要:什么時候需要用到單例模式呢其實單例模式在日常開發中的使用非常的廣泛,例如各種浮窗像登錄浮窗等,無論我們點擊多少次,都是同一個浮窗,浮窗從始至終只創建了一次。這種場景就十分適合運用單例模式。
單例模式 什么是單例模式?
單例模式的定義:一個類僅有一個實例,并且可以在全局訪問。
什么時候需要用到單例模式呢?其實單例模式在日常開發中的使用非常的廣泛,例如各種浮窗、像登錄浮窗等,無論我們點擊多少次,都是同一個浮窗,浮窗從始至終只創建了一次。這種場景就十分適合運用單例模式。
我們創建一個“最老的人”的類,很明顯,“最老的人”有且只有一個。這很符合我們單例模式的運用場景。我們先來看看完整代碼:
var oldestMan = function (name) { this.name = name; } oldestMan.prototype.getName = function () { console.log(this.name); } //引入一個代理函數和閉包的概念 var createOldestMan = (function () { var instance; return function (name) { if (!instance) { instance = new oldestMan(name); } return instance; } })(); var personA = createOldestMan("holz"); var personB = createOldestMan("Amy"); personA.getName(); // holz personB.getName(); // holz
我們可以在控制臺上看到即使調用了兩次createOldestMan并且賦了不一樣的值,但兩次getName()輸出的都是第一次的“holz”。這就是單例模式。
代碼看不太懂?沒關系,現在給大家一一講解。
首先我們創建了一個oldestMan類,創建了一個name屬性。然后我們通過 prototype 給它添加一個getName()方法用來獲取oldestMan的名字,相信到這里大家都是懂的,然后下面一段代碼就是重點了,也比較難理解。我們打這段代碼多帶帶拿出來將一下。
//引入一個代理函數和閉包的概念 var createOldestMan = (function () { var instance; return function (name) { if (!instance) { instance = new oldestMan(name); } return instance; } })();
首先,我們不用管什么是代理函數,之所以叫它代理函數是因為它輔助我們實現單例模式的效果,這段函數第一個關鍵點是 createOldestMan() 是一個立即執行函數。立即函數在聲明的時候就會立即執行,也就是在聲明createOldestMan的時候這個函數就會執行,它會聲明一個instance 變量,然后返回一個函數給createOldestMan。createOldestMan就相當于:
var createOldestMan = function (name) { if (!instance) { instance = new oldestMan(name); } return instance; }
第二個關鍵點是:這里利用了 閉包 的概念。
閉包是什么呢?我只需要記住當函數在定義時的語法作用域之外被調用,卻還能訪問定義時的語法作用域時,就是產生了閉包。
我們來看一下我們的代碼,函數先定義了一個instance,然后再返回一個function(name),這個function(name)里面用到了instance變量。在正常情況下,在立即執行函數執行之后,instance變量就會被JavaScript的垃圾回收機制回收,但是因為function(name)被返回到了外部,而function(name)隨時會被調用,隨時會訪問到instance變量,所以instance變量被保留在了內存中。這就產生了閉包。也就是說,function(name)被賦值給了外部的createOldestMan,在外部的語法作用域中執行,但還可以訪問到定義時內部的語法作用域中的instance。
所以在 立即執行函數 和 閉包 的作用下,instance只被申請了一次,也就是只有一個instance。也就是說,我們無論執行多少次createOldestMan("..."),instance只會是第一次的那個值。所以我們就可以判斷instance是否已經被實例化了,來給instance賦值,如果instance已經被實例化,就返回instance。這就達到了一個類只有一個實例的效果。
通用的單例模式我還可以改造一下代碼,因為在開發中,我們可能不僅只有一個單例,所以我們應該讓代碼能夠變得各個單例通用。我們應該在哪里改呢?沒錯,改代理函數。我們只需要把代理函數中的oldestMan()提取出來,改為以參數的形式傳值,不局限于oldestMan()。
var singleObj; var createSingleton = function (fn) { return function (text) { if (!singleObj) { singleObj = new fn (text); } return singleObj; } }
這樣我們就可以把單例作為參數傳進去,用它實現不同的單例了。
完整代碼是這樣的:
var oldestMan = function (name) { this.name = name; } oldestMan.prototype.getName = function () { console.log(this.name); } //一個通用的代理函數 var singleObj; var createSingleton = function (fn) { return function (text) { if (!singleObj) { singleObj = new fn (text); } return singleObj; } } var person_1 = createSingleton(oldestMan)("holz"); var person_2 = createSingleton(oldestMan)("tom"); person_1.getName(); //holz person_2.getName(); //holz
同樣,即使再次調用createSingleton并傳入不同的值,輸出的依舊是第一次的“holz”。
總結單例模式的定義:一個類僅有一個實例,并且可以在全局訪問。
適用場景:其實單例模式在日常開發中的使用非常的廣泛,例如各種浮窗、像登錄浮窗等,無論我們點擊多少次,都是同一個浮窗,浮窗從始至終只創建了一次。這種場景就十分適合運用單例模式。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/90370.html
摘要:使用構造函數如果被實例化過,就返回實例化的結果這種方式比較簡潔,通過判斷是否已經實例化過,但是也沒啥安全性,如果在外部修改那很可能單例模式就被破壞了。 摘要 單體模式也有人稱為單例模式,是javaScript 中最基本但又最有用的模式之一。 什么是單體 一講到概念第一反應就是WTFshowImg(https://segmentfault.com/img/bVSUdx?w=600&h=3...
摘要:本系列為設計模式與開發實踐作者曾探學習總結,如想深入了解,請支持作者原版單例模式實現單例模式單例模式的定義是保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。 本系列為《JavaScript設計模式與開發實踐》(作者:曾探)學習總結,如想深入了解,請支持作者原版 單例模式 實現單例模式 單例模式的定義是:保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。單例模式是一種常用的模式...
摘要:訂閱模式的一個典型的應用就是后面會寫一篇相關的讀書筆記。享元模式享元模式的核心思想是對象復用,減少對象數量,減少內存開銷。適配器模式對目標函數進行數據參數轉化,使其符合目標函數所需要的格式。 設計模式 單例模式 JS的單例模式有別于傳統面向對象語言的單例模式,js作為一門無類的語言。使用全局變量的模式來實現單例模式思想。js里面的單例又分為普通單例和惰性單例,惰性單例指的是只有這個實例...
摘要:橋接模式的核心在于將抽象部分和它的實現部分分離,使它們都可以獨立的變化。看起來這個版本已經很完美了不,它仍然有可以優化的空間,即題目提到的橋接模式。使用橋接模式的實現版本這個實現包含了三個函數。這個例子體現了橋接模式的作用。 我寫的程序員面試系列文章 Java面試系列-webapp文件夾和WebContent文件夾的區別? 程序員面試系列:Spring MVC能響應HTTP請求的原因?...
本回內容介紹 上一回聊到JS中模擬接口,裝飾者模式,摻元類,分析了backbone的繼承源碼,感覺還好吧! 介一回,偶們來聊一下在JS單例模式(singleton),單例模式其實運用很廣泛,比如:jquery,AngularJS,underscore吖蝦米的都是單例模式,來吧,直接開始咯: 1. 單例模式 保證一個類只有一個實例,從全局命名空間里提供一個唯一的訪問點來訪問該對象。其實之前寫過的對象...
閱讀 2936·2021-10-14 09:43
閱讀 2877·2021-10-14 09:42
閱讀 4661·2021-09-22 15:56
閱讀 2367·2019-08-30 10:49
閱讀 1593·2019-08-26 13:34
閱讀 2380·2019-08-26 10:35
閱讀 601·2019-08-23 17:57
閱讀 2027·2019-08-23 17:15