為什么要用單例,你真的會寫單例模式嗎


優秀的設計結構可以規避很多潛在的性能問題,對系統性能的影響可能遠遠大於代碼的優化,所以我們需要知道一些設計模式和方法。

單例模式:

單例模式是一種對象創建模式,用於生產一個對象的實例,它可以確保系統中一個類只產生一個實例,這樣做有兩個好處:

1.對於頻繁使用的對象,可以省略創建對象所花費的時間,這對於那些重量級對象而言,是非常可觀的一筆系統開銷。

2.由於new操作的次數減少,所以系統內存的使用評率也會降低,這將減少GC壓力,縮短GC停頓時間。

由於以上兩點可知單例模式的使用對於系統的關鍵組件和頻繁使用的對象來說是可以有效的改善系統的性能的。

單例的核心是通過一個方法返回唯一的一個對象實例,首先單例類必須有一個private訪問級別的構造函數,因為,只有這樣,才能保證單例不會再系統中的其他代碼內被實例化,其次,instance成員變量和getInstance方法必須是static的。

需要對instance實例做延遲加載

假如單例的創建過程很慢(構造方法中有其他耗時操作),並且不是延遲加載的(由於instance成員變量是static定義的,因此在JVM加載單例類時,單例對象就會被創建),如果此時這個單例類還在系統中扮演着其他角色(單例類還有其他非創建單例的靜態方法),那么在任何使用這個單例類的地方都會初始化這個單例變量,而不管是否會被用到。也就是說雖然並沒有使用單例類,但是它還是被創建出來了,這是我們不願意看到的,為了解決這個問題,就需要引入延遲加載機制。

對於靜態變量instance初始值賦null,確保系統啟動時沒有額外的負載,在getInstance()工廠方法中,判斷當前單例是否已存在,若存在則返回,若不存在則創建單例,同時getInstance()方法應該是同步的。

為了延遲加載而引入同步關鍵字會降低系統性能,為了解決這個問題,可以使用內部類來維護單例的實例,當單例類被加載時,其內部類並不會被初始化,所以可以確保單例類被加載進入JVM時,不會初始化單例類,而當getInstance方法被調用時才會加載SingletonHolder從而初始化instance,由於實例的建立是在類加載時完成,故天生對多線程友好,getInstance方法也不需要使用同步關鍵字,所以這種方法兼容上邊說的兩種實現的優點。

通常情況下,以上方式實現的單例已經可以確保在系統中中存在唯一的實例了,但是也有例外的情況導致系統生成多個實例,比如,在代碼中通過反射機制強行調用單例類的私有構造函數來生成多個單例。針對這種極端的情況也有克服的辦法,具體辦法請參考筆者頭條號中講解單例模式的其他兩篇文章。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM