摘要:單例類如果一個類始終只能創建一個實例,則這個類被稱為單例類在一些特殊場景下,要求不允許自由創建該類的對象,而只允許為該類創建一個對象。
單例(Singleton)類
如果一個類始終只能創建一個實例,則這個類被稱為單例類
在一些特殊場景下,要求不允許自由創建該類的對象,而只允許為該類創建一個對象。為了避免其他類自由創建該類的實例,應該把該類的構造器使用private修飾,從而把該類的所有構造器隱藏起來
根據良好封裝的原則:一旦把該類的構造器隱藏起來,就需要一個public方法作為該類的訪問點,用于創建該類的對象,且該方法必須使用static修飾(因為調用該方法之前還不存在對象,因此調用該方法的不可能是對象,只能是類)
除此之外,該類還必須緩存已經創建的對象,否則該類無法知道是否曾經創建過對象,也就無法保證只創建了一個對象。為此該類需要使用一個成員變量來保存曾經創建的對象,因為該成員變量需要被上面的靜態方法訪問,故該成員變量必須使用static修飾
class Singleton { // 使用一個類變量來緩存曾經創建的實例 private static Singleton instance; // 將構造器使用private修飾,隱藏該構造器 private Singleton(){} // 提供一個靜態方法,用于返回Singleton實例 // 該方法可以加入自定義的控制,保證只產生一個Singleton對象 public static Singleton getInstance() { // 如果instance為null,表明還不曾創建Singleton對象 // 如果instance不為null,則表明已經創建了Singleton對象, // 將不會重新創建新的實例 if (instance == null) { // 創建一個Singleton對象,并將其緩存起來 instance = new Singleton(); } return instance; } } public class SingletonTest { public static void main(String[] args) { // 創建Singleton對象不能通過構造器, // 只能通過getInstance方法來得到實例 Singleton s1 = Singleton.getInstance(); Singleton s2 = Singleton.getInstance(); System.out.println(s1 == s2); // 將輸出true } }Coding
代碼一:
public class Singleton { private Singleton() {} // 關鍵點0:構造函數是私有的 private static Singleton single = null; // 關鍵點1:聲明單例對象是靜態的 public static Singleton GetInstance() // 通過靜態方法來構造對象 { if (single == null) { // 關鍵點2:判斷單例對象是否已經被構造 single = new Singleton(); } return single; } }
代碼一是線程不安全的,遇到多線程的并發條件下,有可能給new出多個單例實例
========================================================================================
代碼二:
public class Singleton { private Singleton() {} // 關鍵點0:構造函數是私有的 private static Singleton single = null; // 關鍵點1:聲明單例對象是靜態的 private static Object obj= new Object(); public static Singleton GetInstance() // 通過靜態方法來構造對象 { if (single == null) // 關鍵點2:判斷單例對象是否已經被構造 { lock(obj) // 關鍵點3:加線程鎖 { single = new Singleton(); } } return single; } }
在關鍵點2,檢測單例是否被構造。雖然這里判斷了一次,但是由于某些情況下,可能有延遲加載或者緩存的原因,只有關鍵點2這一次判斷,仍然不能保證系統是否只創建了一個單例,也可能出現多個實例的情況
========================================================================================
代碼三:
public class Singleton { private Singleton() {} // 關鍵點0:構造函數是私有的 private static Singleton single = null; // 關鍵點1:聲明單例對象是靜態的 private static object obj= new object(); public static Singleton GetInstance() // 通過靜態方法來構造對象 { if (single == null) // 關鍵點2:判斷單例對象是否已經被構造 { lock(obj) // 關鍵點3:加線程鎖 { if(single == null) // 關鍵點4:二次判斷單例是否已經被構造 { single = new Singleton(); } } } return single; } }
在判斷單例實例是否被構造時,需要檢測兩次,在線程鎖之前判斷一次,在線程鎖之后判斷一次,再去構造實例
單例模式關鍵點單例是為了保證系統中只有一個實例,其關鍵點有:
私有構造函數
聲明靜態單例對象
構造單例對象之前要加鎖(lock一個靜態的object對象)
需要兩次檢測單例實例是否已經被構造,分別在鎖之前和鎖之后
單例模式問答 為何要檢測兩次?如上面所述,有可能延遲加載或者緩存原因,造成構造多個實例,違反了單例的初衷
構造函數能否公有化?不行,單例類的構造函數必須私有化,單例類不能被實例化,單例實例只能靜態調用
lock住的對象為什么要是object對象,可以是int嗎?不行,鎖住的必須是個引用類型。如果鎖值類型,每個不同的線程在聲明的時候值類型變量的地址都不一樣,那么上個線程鎖住的東西下個線程進來會認為根本沒鎖,相當于每次都鎖了不同的門。引用類型的變量地址是相同的,每個線程進來判斷鎖都想是否被鎖的時候都是判斷同一個地址,相當于是鎖在通一扇門,起到了鎖的作用
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/66498.html
摘要:使用靜態類體現的是基于對象,而使用單例設計模式體現的是面向對象。二編寫單例模式的代碼編寫單例模式的代碼其實很簡單,就分了三步將構造函數私有化在類的內部創建實例提供獲取唯一實例的方法餓漢式根據上面的步驟,我們就可以輕松完成創建單例對象了。 前言 只有光頭才能變強 回顧前面: 給女朋友講解什么是代理模式 包裝模式就是這么簡單啦 本來打算沒那么快更新的,這陣子在刷Spring的書籍。在看...
摘要:如果需要防范這種攻擊,請修改構造函數,使其在被要求創建第二個實例時拋出異常。單例模式與單一職責原則有沖突。源碼地址參考文獻設計模式之禪 定義 單例模式是一個比較簡單的模式,其定義如下: 保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。 或者 Ensure a class has only one instance, and provide a global point of ac...
摘要:總結我們主要介紹到了以下幾種方式實現單例模式餓漢方式線程安全懶漢式非線程安全和關鍵字線程安全版本懶漢式雙重檢查加鎖版本枚舉方式參考設計模式中文版第二版設計模式深入理解單例模式我是一個以架構師為年之內目標的小小白。 初遇設計模式在上個寒假,當時把每個設計模式過了一遍,對設計模式有了一個最初級的了解。這個學期借了幾本設計模式的書籍看,聽了老師的設計模式課,對設計模式算是有個更進一步的認識。...
摘要:總之,選擇單例模式就是為了避免不一致狀態,避免政出多頭。二餓漢式單例餓漢式單例類在類初始化時,已經自行實例化靜態工廠方法餓漢式在類創建的同時就已經創建好一個靜態的對象供系統使用,以后不再改變,所以天生是線程安全的。 概念: Java中單例模式是一種常見的設計模式,單例模式的寫法有好幾種,這里主要介紹兩種:懶漢式單例、餓漢式單例。 單例模式有以下特點: 1、單例類只能有一個實例。 ...
摘要:一般來說,這種單例實現有兩種思路,私有構造器,枚舉。而這種方式又分了飽漢式,餓漢式。通過關鍵字防止指令重排序。什么是單例?為什么要用單例? 一個類被設計出來,就代表它表示具有某種行為(方法),屬性(成員變量),而一般情況下,當我們想使用這個類時,會使用new關鍵字,這時候jvm會幫我們構造一個該類的實例。而我們知道,對于new這個關鍵字以及該實例,相對而言是比較耗費資源的。所以如果我們能夠想...
閱讀 1896·2021-11-22 15:25
閱讀 1257·2021-11-19 09:40
閱讀 1861·2021-09-27 13:57
閱讀 992·2021-09-22 15:10
閱讀 976·2021-08-16 11:01
閱讀 2974·2021-07-23 17:51
閱讀 772·2019-08-30 15:55
閱讀 824·2019-08-30 13:58