單例模式
一.單例模式介紹
單例模式是Java二十三種設(shè)計模式中的一種,也是一種比較常用的設(shè)計模式。其作用是保證該類只能擁有一個實例對象。
二.實現(xiàn)步驟
1.私有化該類的構(gòu)造方法,讓其他類無法通過構(gòu)造器創(chuàng)建該類的實例。
2.提供可以獲取到該類實例的靜態(tài)方法,讓其他類通過該方法獲取到該類的實例。
三.寫法介紹
1.餓漢式
1.1 介紹
因為該類的實例是在類加載的時候就創(chuàng)建出來的,并不是在使用的時候。就像被餓了很久的人見到吃的,不管三七二十一,先填飽肚子再說。所以把這種寫法叫做餓漢式。
1.2 Java代碼
public class Test{
//本類持有本類的引用
private static Test mInstance = new Test();
//將構(gòu)造方法私有化
private Test(){
}
//提供一個對外的方法獲取本類的引用
public static Test getInstance(){
return mInstance;
}
}
1.3 優(yōu)缺點
優(yōu)點:寫法簡單,線程安全,避免了線程同步的問題。
缺點:因為實例是在類加載的時候初始化,所以它的生命周期是和類相同。即使它從未被用到,也不會被系統(tǒng)回收,造成內(nèi)存的浪費。
可以但是不推薦使用餓漢式。
2.懶漢式(基本寫法)
2.1 介紹
該寫法是只有在使用的時候才進行實例創(chuàng)建。就像一個懶漢只有當(dāng)餓了的時候才去吃飯。
2.2 Java代碼
public class Test{
private static Test mInstance;
private Test(){
}
public static Test getInstance(){
if(null = mInstance){
mInstance = new Test();
}
return mInstance;
}
}
2.3 優(yōu)缺點
優(yōu)點:當(dāng)使用的時候才進行實例化,不會造成內(nèi)存的浪費。起到了Lazy Loading的效果。
缺點:在單線程該寫法沒有問題。但是在多線程情況下,是線程不安全的。
不推薦使用該寫法。
3.懶漢式(同步方法)
3.1 介紹
為了解決懶漢式的線程不安全問題,把getInstance()方法進行線程同步。
3.2 Java代碼
public class Test{
private static Test mInstance;
private Test(){
}
public static synchronized Test getInstance(){
if(null == mInstance){
mInstance = new Test();
}
return mInstance;
}
}
*3.3 優(yōu)缺點
優(yōu)點:解決了線程安全問題。
缺點:同步效率低。每次調(diào)用getInstance方法時都要進行同步。但實際上只有當(dāng)mInstance == null時才有同步的必要,不為null時直接return就OK了。
不推薦使用。
4.懶漢式(同步代碼塊)
4.1 介紹
為了解決同步方法效率低而產(chǎn)生的寫法。
4.2 代碼
public class Test{
private static Test mInstance;
private Test(){
}
public static Test getInstance(){
if(null == mInstance){
synchronized(Test.class){
mInstance = new Test();
}
}
return mInstance;
}
}
4.3 優(yōu)缺點
和傳統(tǒng)的懶漢式基本沒區(qū)別。都是線程不安全。
不推薦使用。
5.懶漢式(雙重檢查)
5.1 介紹
在同步方法的基礎(chǔ)上再進行改良的。
5.2
public class Test{
private static volatile Test mInstance;
private Test(){
}
public static Test getInstance(){
if(null == mInstance){
synchronized(Test.class){
if(null == mInstance){
Test = new Test();
}
}
}
return mInstance;
}
}
5.3 優(yōu)缺點
優(yōu)點:這種懶漢式的寫法用到了Double-Check。進行了兩次非空判斷,保證了線程安全,并且只實例化的一次代碼。該寫法線程安全,延遲加載,效率高。
缺點:無。
推薦使用。
6.靜態(tài)內(nèi)部類
6.1 介紹
靜態(tài)內(nèi)部類跟餓漢式方式采用的機制類似,但又不同。兩者都是采用了類裝載的機制來保證初始化實例時只有一個線程。不同的是餓漢式在類被裝載時被實例化,沒有Lazy Loading的作用。而靜態(tài)內(nèi)部類方式在類被裝載時并不會實例化,而是在需要實例化時,才會調(diào)用。
6.2 代碼
public class Test{
private Test(){
}
private static class SingletonInstance{
private static final Test INSTANCE = new Test();
}
public static Test getInstance(){
return SingletonInstance.INSTANCE;
}
}
6.3 優(yōu)缺點
優(yōu)點:利用類的靜態(tài)屬性保證唯一性,JVM保證線程安全,延遲加載,效率高。
推薦使用。
7.枚舉
7.1 代碼
public enum Test{
INSTANCE;
public void whateverMethod(){
}
}
本文章參考了CSDN的博客,這是去往該作者的 鏈接.