參考自百度百科
動機
對于系統(tǒng)中的某些類來說建车,只有一個實例很重要丹喻,例如襟铭,一個系統(tǒng)中可以存在多個打印任務碌奉,但是只能有一個正在工作的任務;一個系統(tǒng)只能有一個窗口管理器或文件系統(tǒng)寒砖;一個系統(tǒng)只能有一個計時工具或ID(序號)生成器赐劣。如在Windows中就只能打開一個任務管理器。如果不使用機制對窗口對象進行唯一化哩都,將彈出多個窗口魁兼,如果這些窗口顯示的內容完全一致,則是重復對象漠嵌,浪費內存資源咐汞;如果這些窗口顯示的內容不一致,則意味著在某一瞬間系統(tǒng)有多個狀態(tài)儒鹿,與實際不符化撕,也會給用戶帶來誤解,不知道哪一個才是真實的狀態(tài)约炎。因此有時確保系統(tǒng)中某個對象的唯一性即一個類只能有一個實例非常重要植阴。
如何保證一個類只有一個實例并且這個實例易于被訪問呢蟹瘾?定義一個全局變量可以確保對象隨時都可以被訪問,但不能防止我們實例化多個對象掠手。一個更好的解決辦法是讓類自身負責保存它的唯一實例憾朴。這個類可以保證沒有其他實例被創(chuàng)建,并且它可以提供一個訪問該實例的方法喷鸽。這就是單例模式的模式動機众雷。
要點
顯然單例模式的要點有三個;一是某個類只能有一個實例做祝;二是它必須自行創(chuàng)建這個實例报腔;三是它必須自行向整個系統(tǒng)提供這個實例。
從具體實現(xiàn)角度來說剖淀,就是以下三點:一是單例模式的類只提供私有的構造函數(shù)纯蛾,二是類定義中含有一個該類的靜態(tài)私有對象,三是該類提供了一個靜態(tài)的公有的函數(shù)用于創(chuàng)建或獲取它本身的靜態(tài)私有對象纵隔。
優(yōu)缺點
優(yōu)點
一翻诉、實例控制
單例模式會阻止其他對象實例化其自己的單例對象的副本,從而確保所有對象都訪問唯一實例捌刮。
二碰煌、靈活性
因為類控制了實例化過程,所以類可以靈活更改實例化過程绅作。
缺點
一芦圾、開銷
雖然數(shù)量很少,但如果每次對象請求引用時都要檢查是否存在類的實例俄认,將仍然需要一些開銷个少。可以通過使用靜態(tài)初始化解決此問題眯杏。
二夜焦、可能的開發(fā)混淆
使用單例對象(尤其在類庫中定義的對象)時,開發(fā)人員必須記住自己不能使用new關鍵字實例化對象岂贩。因為可能無法訪問庫源代碼茫经,因此應用程序開發(fā)人員可能會意外發(fā)現(xiàn)自己無法直接實例化此類。
三萎津、對象生存期
不能解決刪除單個對象的問題卸伞。在提供內存管理的語言中(例如基于.NET Framework的語言),只有單例類能夠導致實例被取消分配锉屈,因為它包含對該實例的私有引用荤傲。在某些語言中(如 C++),其他類可以刪除對象實例部念,但這樣會導致單例類中出現(xiàn)懸浮引用弃酌。
實例
當一個類的實例可以有且只可以一個的時候就需要用到了氨菇。為什么只需要有一個呢?有人說是為了節(jié)約內存妓湘,但這只是單例模式帶來的一個好處查蓉。只有一個實例確實減少內存占用,可是我認為這不是使用單例模式的理由榜贴。我認為使用單例模式的時機是當實例存在多個會引起程序邏輯錯誤的時候豌研。比如類似有序的號碼生成器這樣的東西,怎么可以允許一個應用上存在多個呢唬党?
Singleton模式主要作用是保證在Java應用程序中鹃共,一個類Class只有一個實例存在。
一般Singleton模式通常有三種形式:
第一種形式:懶漢式驶拱,也是常用的形式霜浴。
public class SingletonClass{
private static SingletonClass instance=null;
public static synchronized SingletonClass getInstance(){
if(instance==null){
instance=new SingletonClass();
}
return instance;
}
private SingletonClass(){
}
}
第二種形式:餓漢式
//對第一行static的一些解釋
// java允許我們在一個類里面定義靜態(tài)類。比如內部類(nested class)蓝纲。
//把nested class封閉起來的類叫外部類阴孟。
//在java中,我們不能用static修飾頂級類(top level class)税迷。
//只有內部類可以為static永丝。
public class Singleton{
//在自己內部定義自己的一個實例,只供內部調用
private static final Singleton instance = new Singleton();
private Singleton(){
//do something
}
//這里提供了一個供外部訪問本class的靜態(tài)方法箭养,可以直接訪問
public static Singleton getInstance(){
return instance;
}
}
第三種形式: 雙重鎖的形式慕嚷。
public class Singleton{
private static volatile Singleton instance=null;
private Singleton(){
//do something
}
public static Singleton getInstance(){
if(instance==null){
synchronized(SingletonClass.class){
if(instance==null){
instance=new Singleton();
}
}
}
return instance;
}
}
//這個模式將同步內容下方到if內部,提高了執(zhí)行的效率毕泌,不必每次獲取對象時都進行同步喝检,只有第一次才同步,創(chuàng)建了以后就沒必要了懈词。
//這種模式中雙重判斷加同步的方式蛇耀,比第一個例子中的效率大大提升,因為如果單層if判斷坎弯,在服務器允許的情況下,
//假設有一百個線程译暂,耗費的時間為100*(同步判斷時間+if判斷時間)抠忘,而如果雙重if判斷,100的線程可以同時if判斷外永,理論消耗的時間只有一個if判斷的時間崎脉。
//所以如果面對高并發(fā)的情況,而且采用的是懶漢模式伯顶,最好的選擇就是雙重判斷加同步的方式囚灼。