新聞中心
這篇“Singleton單例模式怎么實(shí)現(xiàn)”文章的知識點(diǎn)大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價(jià)值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“Singleton單例模式怎么實(shí)現(xiàn)”文章吧。
成都創(chuàng)新互聯(lián)-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價(jià)比敦煌網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式敦煌網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋敦煌地區(qū)。費(fèi)用合理售后完善,十多年實(shí)體公司更值得信賴。
Singleton(單例模式)
Singleton(單例模式)屬于創(chuàng)建型模式,提供一種對象獲取方式,保證在一定范圍內(nèi)是唯一的。
意圖:保證一個類僅有一個實(shí)例,并提供一個訪問它的全局訪問點(diǎn)。
其實(shí)單例模式在前端體會的不明顯,原因有:
前端代碼本身在單機(jī)運(yùn)行,創(chuàng)建的任何變量都是天然分布式的,不需要擔(dān)心影響另一個用戶。
后端代碼是一對多的,分辨出哪些資源是請求間共享的,哪些是請求內(nèi)獨(dú)有的很重要。
另外我們說到單例,是隱含了一個范圍的,指的是在某個范圍內(nèi)單例,比如在一個上下文中,還是一個房間中,還是一個進(jìn)程,一個線程中單例,不同場景范圍會不同。
舉例子
如果看不懂上面的意圖介紹,沒有關(guān)系,設(shè)計(jì)模式需要在日常工作里用起來,結(jié)合例子可以加深你的理解,下面我準(zhǔn)備了三個例子,讓你體會什么場景下會用到這種設(shè)計(jì)模式。
多人游戲的共享物品
玩過游戲的同學(xué)都知道,我們在每局游戲中使用的公共物品在當(dāng)前房間中是唯一的,但在游戲房間間卻不是唯一的,所以這些公共物品肯定有不同的類去描述,那每局游戲中怎么拿公共物品,可以保證拿到的是當(dāng)前局內(nèi)唯一的?
Redux 數(shù)據(jù)流
其實(shí)前端的 Redux 數(shù)據(jù)流本身就是單例模式,在一個應(yīng)用中,數(shù)據(jù)是唯一的,但可以有不同的 UI 使用這份唯一的數(shù)據(jù),甚至把一個表格組件展示在兩個不同地方,比如全屏模式,但數(shù)據(jù)依然是一份,我們沒有必要為了全屏展示表格,就讓它再發(fā)一次取數(shù)請求,完全可以和原來的表格共享一份數(shù)據(jù)。
數(shù)據(jù)庫連接池
每個 SQL 查詢都依賴數(shù)據(jù)庫連接池,如果每次查詢都建立一次數(shù)據(jù)庫連接池,則建立連接的速度會遠(yuǎn)遠(yuǎn)慢于 SQL 查詢速度,因此你會怎么設(shè)計(jì)數(shù)據(jù)庫連接池的獲取方法?
意圖解釋
單例模式的意圖很簡單,幾乎就是其字面含義:
意圖:保證一個類僅有一個實(shí)例,并提供一個訪問它的全局訪問點(diǎn)。
對于多人游戲的共享物品,比如一口鍋,要保證在一局游戲內(nèi)唯一,就要提供一種方法訪問到唯一實(shí)例。
Redux 數(shù)據(jù)流的 connect 裝飾器就是全局訪問點(diǎn)的一種設(shè)計(jì)。
數(shù)據(jù)庫連接池可以提前初始化好,并通過固定 API 提供這個唯一實(shí)例。
結(jié)構(gòu)圖
Singleton 是單例模式的接口,客戶只能通過其定義的 instance() 訪問實(shí)例,以保證單例。
代碼例子
下面例子使用 typescript 編寫。
class Ball {
private _instance = undefined
// 構(gòu)造函數(shù)申明為 private,就可以阻止 new Ball() 行為
private constructor() {}
public static instance = () => {
if (this._instance === undefined) {
this._instance = new Ball()
}
return this._instance
}
}
// 使用
const ball = Ball.getInstance()
可以仔細(xì)想想,為什么這個例子把單例寫成了靜態(tài)方法,而不是一個全局變量?其實(shí)全局變量也能解決問題,但由于會污染全局,要盡可能通過模塊化方式解決,上面的例子就是一個較好的封裝方式。
當(dāng)然這只是一個最簡單的例子,實(shí)際上單例模式還有幾種模式:
餓漢式
初始化時就生成一份實(shí)例,這樣調(diào)用時直接就能獲取。
懶漢式
就是代碼例子中寫的,按需實(shí)例化,即調(diào)用的時候再實(shí)例化。
要注意,按需不一定是什么好事,如果 New 的成本很高還按需實(shí)例化,可能把系統(tǒng)異常的風(fēng)險(xiǎn)留到隨機(jī)的觸發(fā)時機(jī),導(dǎo)致難以排查 BUG,另外也會影響第一次實(shí)例化時的系統(tǒng)耗時。
對 JAVA 來說,單例還需要考慮并發(fā)性,有 雙重檢測、靜態(tài)內(nèi)部類、枚舉 等辦法解決,這里不具體展開。
弊端
單例模式的問題有:
對面向?qū)ο蟛惶押?。對封裝、繼承、多態(tài)支持不夠友好。
不利于梳理類之間的依賴關(guān)系。畢竟單例是直接調(diào)用的,而不是在構(gòu)造函數(shù)申明的,所以要梳理關(guān)系要看完每一行代碼才能確定。
可拓展性不好。萬一要支持多例就比較難拓展,比如全局?jǐn)?shù)據(jù)流可能因?yàn)槲⑶岸朔桨父某啥鄬?shí)例、數(shù)據(jù)庫連接池為了分治 SQL 改成多實(shí)例,都是有可能的,在系統(tǒng)設(shè)計(jì)之初就要考慮到未來是否還會保持單例。
可測試性不好,因?yàn)閱卫侨止蚕淼?,無法保證測試用例間的隔離。
無法使用構(gòu)造函數(shù)傳參。
另外單例模式還可以被工廠方法所替代,所以不用特別糾結(jié)一種設(shè)計(jì)模式,可以結(jié)合使用,工廠函數(shù)也可以內(nèi)嵌單例模式。
以上就是關(guān)于“Singleton單例模式怎么實(shí)現(xiàn)”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對大家有幫助,若想了解更多相關(guān)的知識內(nèi)容,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
新聞名稱:Singleton單例模式怎么實(shí)現(xiàn)
文章源于:http://fisionsoft.com.cn/article/gdepcs.html