單例模式是所有設計模式中最簡單的模式,也是我們平常經常用到的,單例模式通常被我們應用於執行緒池、快取操作、佇列操作等等。
單例模式旨在建立乙個類的例項,建立乙個類的例項我們用全域性靜態變數或者約定也能辦到單例的作用,為什麼我們要用單例模式?
接下來我們就從如何形成單例模式,單例模式建立的過程來講解。
我們平常建立乙個物件需要new物件,假如有乙個物件objectclass我們例項化它。
new objectclass()如果另外乙個類要使用objectclass則可以再通過new來建立另外乙個例項化,如果這個類是public 則我們可以在使用的時候多次例項化物件。
那我們怎麼保證類不被其他類例項化,利用private關鍵字我們可以採用私有建構函式來阻止外部例項化該類。
public class objectclass這樣一來我們無法例項化objectclass則我們就無法使用它。那我們要怎麼例項化呢?}
由於私有構造方法我們只能在內部訪問,所以我們可以用乙個內部方法例項化objectclass,為了外部能夠訪問這個方法我們將這個方法設定成static。
這樣做了之後確保返回物件始終是第一次建立的物件,我們用乙個私有靜態物件來儲存例項化的物件,如果物件沒建立我們則立即建立,如果已經建立就返回已經建立的物件。
public class objectclass到這裡我們的單例模式就形成了,單例模式定義:public static objectclass getsingletone()
return singleton;}}
單例模式:確保乙個類只有乙個例項,並提供乙個全域性訪問點。
啟用多執行緒測試單例返回物件
如圖中做的測試一樣,我啟了10個執行緒獲得單例物件然後列印物件的hashcode。測試發現有hashcode不一致的情況,證明單例返回的物件並不是只有乙個。
因為多執行緒執行的時候可能會同時進行if (singleton == null)的判斷,如果此時singleton變數還沒被例項化則可能有多個執行緒進入到例項化**,以至於返回的例項化物件不是同乙個。
由於多執行緒導致if檢查變數問題,則爭對檢查問題我們可以有兩類解決辦法:
①"急切"建立例項,不用延遲例項化做法
急切例項化就是在靜態初始化器中建立物件,這樣就保證了程式執行階段單例物件已經建立好,去除if判斷。
public class objectclass②加鎖為了讓建立物件只能有乙個執行緒操作,則我們對建立物件**進行加鎖處理,再次改造getsingletone方法。public static objectclass getsingletone()
}
public class objectclass加鎖對效能有一定的損耗,如果你的系統對效能要求比較高,我們對於加鎖的處理還有一種優化方式:雙重檢查加鎖public static objectclass getsingletone()
}return singleton;}}
public static objectclass getsingletone()} }使用雙重檢查加鎖,則多執行緒在執行的時候如果已經建立了單例物件後就不會再進入到lock**段以此減少鎖帶來的效能損耗。return singleton;
}
然後我們再來測試一波,啟用50個執行緒,可以看到輸出的hashcode是一致的。
回到我們開始講的為什麼不用全域性變數或者約定來解決單例問題,因為對於我們開發來說雖然有約定但是我們不能保證每個人都按照約定或者濫用全域性變數造成問題。
而使用單例模式能進行更好的自我約定和管理,當然我們也有可能會濫用單例模式,這就需要對它能解決什麼問題如何使用深入理解。
設計模式並不是要生搬硬套,而是在需要的時候符合的場景進行合理使用。
雖然單例模式比較簡單,但通過分析我們看到問題也不少,要更好的使用需要我們更好的分析,也希望這篇博文對你有些幫助。
HeadFirst設計模式 單例模式
單例模式 我們首先提出的疑問是什麼是單例模式,為什麼需要單例模式?比如有的時候我們對一些物件只用乙個,比如執行緒池。快取等等。如何保障乙個例項的執行呢?或許我們可以使用全域性變數,不過全域性變數只能提供全域性訪問,不能確保只有乙個例項。全域性變數一旦多了,通常有的時候我們自己都忘記了。這點深有感觸。...
Head First 設計模式 5 單例模式
單例模式 確保乙個類只有乙個例項,並提供乙個全域性訪問點。用到的設計原則 1 封裝變化 2 組合優於整合 3 針對介面變成而不是針對實現 4 為互動物件之間的松耦合設計而努力 5 類應該對擴充套件開放,對修改關閉 6 依賴抽象,而不是依賴具體類 最簡單的單例 class singleton publ...
單例模式 基於headfirst設計模式的總結
1.經典的單例模式 懶漢式 public class singleton public static singleton getinstance return uniqueinstance other useful methods here 主要的就是3步 1.建立靜態私有變數 2.建立私有構造方法...