摘要:但是如何在對構造函數使用操作符創建多個對象的時候僅獲取一個單例對象呢。單例的實例引用單例構造函數單例私有屬性和方法暴露出來的對象改進之前在構造函數中重寫自身會丟失所有在初始定義和重定義之間添加到其中的屬性。
1. 單例模式
單例模式 (Singleton) 的實現在于保證一個特定類只有一個實例,第二次使用同一個類創建新對象的時候,應該得到與第一次創建對象完全相同的對象。
當創建一個新對象時,實際上沒有其他對象與其類似,因為新對象已經是單例了 {a:1} === {a:1} // false 。
但是如何在對構造函數使用 new 操作符創建多個對象的時候僅獲取一個單例對象呢。
2. 靜態屬性中的實例在構造函數的靜態屬性中緩存該實例,缺點在于 instance 屬性是公開可訪問的屬性,在外部代碼中可能會修改該屬性。
function Universe() { if (typeof Universe.instance === "object") { // 判斷是否已經有單例了 return Universe.instance } Universe.instance = this return this } var uni1 = new Universe() var uni2 = new Universe() uni1 === uni2 // true3. 閉包中的實例
可以把實例封裝在閉包中,這樣可以保證該實例的私有性并且保證該實例不會在構造函數之外被修改,代價是帶來了額外的閉包開銷。
function Universe() { var instance = this Universe = function() { // 重寫構造函數 return instance } } var uni1 = new Universe() var uni2 = new Universe() uni1 === uni2 // true
當第一次調用構造函數時,它正常返回 this ,然后在以后調用時,它將會執行重寫構造函數,這個構造函數通過閉包訪問了私有 instance 變量,并且簡單的返回了該 instance。
4. 惰性單例有時候對于單例對象需要延遲創建,所以在單例中還存在一種延遲創建的形式,也有人稱之為惰性創建。
const LazySingle = (function() { let _instance // 單例的實例引用 function Single() { // 單例構造函數 const desc = "單例" // 私有屬性和方法 return { // 暴露出來的對象 publicMethod: function() {console.log(desc)}, publickProperty: "1.0" } } return function() { return _instance || (_instance = Single()) } })() console.log(LazySingle()===lazySingle()) // true console.log(LazySingle().publickProperty) // 1.05. 改進
之前在構造函數中重寫自身會丟失所有在初始定義和重定義之間添加到其中的屬性。在這種情況下,任何添加到 Universe() 的原型中的對象都不會存在指向由原始實現所創建實例的活動鏈接:
function Universe() { var instance = this Universe = function() { return instance } } Universe.prototype.nothing = true var uni1 = new Universe() Universe.prototype.enthing = true var uni2 = new Universe() console.log(uni1 === uni2) // true uni1.nothing // true uni2.nothing // true uni1.enthing // undefined uni2.enthing // undefined uni1.constructor.name // "Universe" uni1.constructor === Universe // false
之所以 uni1.constructor 不再與 Universe() 相同,是因為uni1.constructor仍然指向原始的構造函數,而不是重定義之后的那個構造函數。
可以通過一些調整實現原型和構造函數指針按照預期的那樣運行:
function Universe() { var instance Universe = function Universe() { return instance } Universe.prototype = this // 保留原型屬性 instance = new Universe() instance.constructor = Universe // 重置構造函數指針 instance.start_time = 0 // 一些屬性 instance.big = "yeah" return instance } Universe.prototype.nothing = true var uni1 = new Universe() Universe.prototype.enthing = true var uni2 = new Universe() console.log(uni1 === uni2) // true uni1.nothing & uni2.nothing & uni1.enthing & uni2.enthing // true uni1.constructor.name // "Universe" uni1.constructor === Universe // true uni1.big // "yeah" uni2.big // "yeah"
本文是系列文章,可以相互參考印證,共同進步~
JS 抽象工廠模式
JS 工廠模式
JS 建造者模式
JS 原型模式
JS 單例模式
JS 回調模式
JS 外觀模式
JS 適配器模式
JS 利用高階函數實現函數緩存(備忘模式)
JS 狀態模式
JS 橋接模式
JS 觀察者模式
網上的帖子大多深淺不一,甚至有些前后矛盾,在下的文章都是學習過程中的總結,如果發現錯誤,歡迎留言指出~
參考:
《JavaScript模式》 P143
《Javascript 設計模式》 - 張榮銘
設計模式之單例模式
PS:歡迎大家關注我的公眾號【前端下午茶】,一起加油吧~
另外可以加入「前端下午茶交流群」微信群,長按識別下面二維碼即可加我好友,備注加群,我拉你入群~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/92144.html
摘要:文章系列設計模式單例模式設計模式策略模式設計模式代理模式概念單例模式的定義是保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。在開發中,單例模式的用途同樣非常廣泛。 前言 本系列文章主要根據《JavaScript設計模式與開發實踐》整理而來,其中會加入了一些自己的思考。希望對大家有所幫助。 文章系列 js設計模式--單例模式 js設計模式--策略模式 js設計模式--代理模式 概念...
摘要:什么是設計模式設計模式是一種能夠被反復使用,符合面向對象特性的代碼設計經驗的總結,合理的使用設計模式能夠讓你得代碼更容易維護和可靠設計模式的類型共分為創建型模式,結構型模式,行為型模式三種創建型模式創建型模式是對一個類的實例化過程進行了抽象 什么是設計模式 設計模式是一種能夠被反復使用,符合面向對象特性的代碼設計經驗的總結,合理的使用設計模式能夠讓你得代碼更容易維護和可靠設計模式的類型...
摘要:什么是單例模式單例模式是一種十分常用但卻相對而言比較簡單的單例模式。對象就是單例模式的體現。總結單例模式雖然簡單,但是在項目中的應用場景卻是相當多的,單例模式的核心是確保只有一個實例,并提供全局訪問。 1. 什么是單例模式? 單例模式是一種十分常用但卻相對而言比較簡單的單例模式。它是指在一個類只能有一個實例,即使多次實例化該類,也只返回第一次實例化后的實例對象。單例模式不僅能減少不必要...
閱讀 2568·2023-04-25 17:33
閱讀 648·2021-11-23 09:51
閱讀 2951·2021-07-30 15:32
閱讀 1395·2019-08-29 18:40
閱讀 1940·2019-08-28 18:19
閱讀 1465·2019-08-26 13:48
閱讀 2237·2019-08-23 16:48
閱讀 2275·2019-08-23 15:56