您好,登錄后才能下訂單哦!
這篇“Singleton單例模式怎么實現”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“Singleton單例模式怎么實現”文章吧。
Singleton(單例模式)
Singleton(單例模式)屬于創建型模式,提供一種對象獲取方式,保證在一定范圍內是唯一的。
意圖:保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。
其實單例模式在前端體會的不明顯,原因有:
前端代碼本身在單機運行,創建的任何變量都是天然分布式的,不需要擔心影響另一個用戶。
后端代碼是一對多的,分辨出哪些資源是請求間共享的,哪些是請求內獨有的很重要。
另外我們說到單例,是隱含了一個范圍的,指的是在某個范圍內單例,比如在一個上下文中,還是一個房間中,還是一個進程,一個線程中單例,不同場景范圍會不同。
舉例子
如果看不懂上面的意圖介紹,沒有關系,設計模式需要在日常工作里用起來,結合例子可以加深你的理解,下面我準備了三個例子,讓你體會什么場景下會用到這種設計模式。
多人游戲的共享物品
玩過游戲的同學都知道,我們在每局游戲中使用的公共物品在當前房間中是唯一的,但在游戲房間間卻不是唯一的,所以這些公共物品肯定有不同的類去描述,那每局游戲中怎么拿公共物品,可以保證拿到的是當前局內唯一的?
Redux 數據流
其實前端的 Redux 數據流本身就是單例模式,在一個應用中,數據是唯一的,但可以有不同的 UI 使用這份唯一的數據,甚至把一個表格組件展示在兩個不同地方,比如全屏模式,但數據依然是一份,我們沒有必要為了全屏展示表格,就讓它再發一次取數請求,完全可以和原來的表格共享一份數據。
數據庫連接池
每個 SQL 查詢都依賴數據庫連接池,如果每次查詢都建立一次數據庫連接池,則建立連接的速度會遠遠慢于 SQL 查詢速度,因此你會怎么設計數據庫連接池的獲取方法?
意圖解釋
單例模式的意圖很簡單,幾乎就是其字面含義:
意圖:保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。
對于多人游戲的共享物品,比如一口鍋,要保證在一局游戲內唯一,就要提供一種方法訪問到唯一實例。
Redux 數據流的 connect 裝飾器就是全局訪問點的一種設計。
數據庫連接池可以提前初始化好,并通過固定 API 提供這個唯一實例。
結構圖
Singleton 是單例模式的接口,客戶只能通過其定義的 instance() 訪問實例,以保證單例。
代碼例子
下面例子使用 typescript 編寫。
class Ball {
private _instance = undefined
// 構造函數申明為 private,就可以阻止 new Ball() 行為
private constructor() {}
public static instance = () => {
if (this._instance === undefined) {
this._instance = new Ball()
}
return this._instance
}
}
// 使用
const ball = Ball.getInstance()
可以仔細想想,為什么這個例子把單例寫成了靜態方法,而不是一個全局變量?其實全局變量也能解決問題,但由于會污染全局,要盡可能通過模塊化方式解決,上面的例子就是一個較好的封裝方式。
當然這只是一個最簡單的例子,實際上單例模式還有幾種模式:
餓漢式
初始化時就生成一份實例,這樣調用時直接就能獲取。
懶漢式
就是代碼例子中寫的,按需實例化,即調用的時候再實例化。
要注意,按需不一定是什么好事,如果 New 的成本很高還按需實例化,可能把系統異常的風險留到隨機的觸發時機,導致難以排查 BUG,另外也會影響第一次實例化時的系統耗時。
對 JAVA 來說,單例還需要考慮并發性,有 雙重檢測、靜態內部類、枚舉 等辦法解決,這里不具體展開。
弊端
單例模式的問題有:
對面向對象不太友好。對封裝、繼承、多態支持不夠友好。
不利于梳理類之間的依賴關系。畢竟單例是直接調用的,而不是在構造函數申明的,所以要梳理關系要看完每一行代碼才能確定。
可拓展性不好。萬一要支持多例就比較難拓展,比如全局數據流可能因為微前端方案改成多實例、數據庫連接池為了分治 SQL 改成多實例,都是有可能的,在系統設計之初就要考慮到未來是否還會保持單例。
可測試性不好,因為單例是全局共享的,無法保證測試用例間的隔離。
無法使用構造函數傳參。
另外單例模式還可以被工廠方法所替代,所以不用特別糾結一種設計模式,可以結合使用,工廠函數也可以內嵌單例模式。
以上就是關于“Singleton單例模式怎么實現”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。