說到單例模式,應該是設計模式裡面最簡單也最容易理解的乙個模式了。只要是有過工作經驗的程式猿,閉著眼睛應該也能寫出乙個單例模式的例子。不過呢,如果抱著學究精神來看單例模式,裡面的水也是不淺的。
乙個類有且僅有乙個例項,並且自行例項化向整個系統提供。這一模式的目的是使得類的乙個物件成為系統中的唯一例項。要實現這一點,可以從客戶端對其進行例項化開始。因此需要用一種只允許生成物件類的唯一例項的機制,「阻止」所有想要生成物件的訪問。使用工廠方法來限制例項化過程。這個方法應該是靜態方法(類方法),因為讓類的例項去生成另乙個唯一例項毫無意義。
簡單理解單例模式的概念後,恐怕很容易就能寫出如下**:
public class ehsingleton
public static ehsingleton getinstance()
public void dosomething()
}
這就是單例模式中最容易寫出來的「餓漢模式」,這樣寫簡單明瞭,執行緒安全,全系統只有乙個地方去例項化物件,絕對意義上的單例。但是遇到吹毛求疵的人,會告訴你,這樣做太粗暴了,我還沒確定要用,你就給我例項化出來了,影響效能,浪費記憶體。
好吧,只能優化一下,看看如下**:
public class lhsingleton
public static synchronized lhsingleton getinstance()
return sinstance;
}public void dosomething()
}
這是單例模式中的「懶漢模式」,用到的時候才去例項化物件,通過if判斷確保例項只有乙個,並且工廠方法上加了鎖,確保執行緒安全。那這樣做是不是就完美了呢?當然不是,方法上加鎖,意味著每次執行這個方法都是阻塞的。實際上只有第一次例項化物件的時候需要執行緒安全,當物件不為空時,是不需要執行緒安全的。方法上加鎖,無疑是影響了效能。
好吧,繼續優化一下,把鎖放到例項化物件的**上,**如下:
public class dclsingleton
public static dclsingleton getinstance() }}
return sinstance;
}public void dosomething()
}
雙重檢查模式(dcl模式),這樣既做到了例項物件懶載入,又確保了執行緒安全,還不會影響效能。但是這裡有乙個爭議, 就是有理論上的概率會出現指令重排序的問題。關於指令重排序的問題需要深入到jvm虛擬機器去分析,才能得到這個理論上的概率。實際中去做併發測試,估計很難測出這個問題。但是很小的概率如果遇到像雙十一這樣的併發量,這個概率可能會大大的增加。所以最完美的**應該是這樣的:
public class dclsingleton
public static dclsingleton getinstance() }}
return sinstance;
}public void dosomething()
}
給例項變數加上volatile關鍵字,確保萬無一失,真正意義上做到完美。
public class innerclasssingleton
private static class singletonholder
public static innerclasssingleton getinstance()
public void dosomething()
}
public enum enumsingleton
}
內部類模式和列舉模式,這兩種方法都優雅的實現了單例模式,而且執行緒安全,效能也沒影響。個人比較推薦內部類模式,**的可讀性更強一些。 最簡單的單例模式
1.啥是單例模式?答 單例模式就是乙個類只有乙個例項 2.為啥不用全域性變數來實現呢?答 因為單例模式既能有全域性變數的優點,可以全域性訪問,但是沒有全域性變數的缺點 3.啥缺點?答 如果我們要在乙個全域性指令碼中放乙個物件,那麼我們要在程式執行前就建立好,如果是開發遊戲,我們要在遊戲執行前建立好這...
最簡單的單例模式
如果乙個類始終只能建立乙個例項,則這個類被稱為單例類。在一些特殊的場景下,要求不允許自由建立該類的物件,而是只允許為該類建立乙個物件。為了避免其他類自由建立該類的例項,我們把該類的構造器使用private修飾,從而把該類的所有構造器隱藏起來。根據良好封裝的原則 一單把該類的構造器隱藏起來,則需要提供...
單例模式最簡單可靠的寫法
單例模式大家都知道有兩種方式,一種是餓漢式,一種是懶漢式 餓漢式 一開始就初始化例項 public class singleton public static singleton getinstance 懶漢式,記住這種雙重檢查的方式,保證執行緒的安全 public class singleton ...