單例模式是最常見的設計模式之一。一般介紹單例模式的書籍都會介紹兩種,餓漢式和懶漢式,但是除了這兩種方式以外,本文還會介紹其他幾種單例模式的實現方式,並對比其中的優缺點。
一句話概括一下,定義為單例物件的類只能有乙個例項存在。
1、將構造器私有化,這樣可以保證其他**無法通過構造器來呼叫該類的構造方法例項化物件。
2、提供靜態的getinstance方法給外部進行呼叫,以獲取該類的例項。
單例模式在多執行緒的場景下要多加小心。如果當唯一例項尚未建立,此時有多個執行緒同時來建立該類的例項,那麼就會有機率造成產生不同的例項物件,從而違反了單例模式中例項唯一的原則。
public class hungrystatic
//靜態屬性例項物件
private static final hungrystatic hungrystatic = new hungrystatic();
//提供靜態的getinstance方法
public static hungrystatic getinstance()
}
優點:這種方法比較簡單,在類載入的時候就例項化了物件,避免的執行緒同步的問題,並且執行效率高。
缺點:在類載入的時候就例項化了物件,沒有達到延遲載入的目的,如果這個類沒有用到,那麼就會造成資源的浪費。
/**
* 餓漢式(靜態**塊)
*/public class hungrystaticarea
private static hungrystaticarea hungrystaticarea;
//在靜態**塊中例項化物件
static
//提供靜態的getinstance方法獲取例項物件
public static hungrystaticarea getinstance()
}
這種方式優缺點與第一種相同,也是在類載入的時候就例項化了物件。
public class lazynotsafe
private static lazynotsafe lazynotsafe;
//呼叫getinstance方法的時候才去生成該類的例項
public static lazynotsafe getinstance()
return lazynotsafe;
}}
這種方式起到了延遲載入的效果,但是只能用於單執行緒場景下。如果用於多執行緒場景,多個執行緒同時進入了對==null的判斷,就有可能會造成產生多個例項。所以在多執行緒的場景下不適合用此方法。
/**
* 懶漢式(執行緒安全,同步方法)
*/public class lazysycrolize
private static lazysycrolize lazysycrolize;
//在getinstance方法上增加synchronized 關鍵字,加同步鎖
public static synchronized lazysycrolize getinstance()
}
在getinstance方法上增加同步的關鍵字synchronized,解決了在3中遇到的多執行緒安全問題。但是這種方式有乙個很大的缺點就是效率特別低,所以不推薦使用。
/**
* 懶漢式(雙重檢查)
*/public class lazydoublechk
private static volatile lazydoublechk lazydoublechk;
public static lazydoublechk getinstance()}}
return lazydoublechk;
}}
優點:執行緒安全,延遲載入,效率較高。
/**
* 懶漢式(靜態內部類)
*/public class lazyinner
//靜態內部類,在內部類中例項化該物件
private static class lazyinnerinstance
public static lazyinner getinstance()
}
這種方式和餓漢式方式採用的機制類似,但是又有不同。兩者都採用的類載入機制來保證例項化物件的時候只有乙個。不同的地方在於餓漢式只要改類被裝在就會例項化,沒有延遲載入的作用。而靜態內部類在該類狀態的時候不會立即被例項化,只要呼叫getinstance方法才回去例項化。
優點:避免了執行緒不安全,延遲載入,效率高。
/**
* spring ioc 中使用的單例模式
*/public class registermap
//這裡使用concurrenthashmap 保證map執行緒的安全性
private static mapregister = new concurrenthashmap();
public static registermap getinstance(string name)
if(register.get(name)==null)
return (registermap) register.get(name);
}}
註冊式登記,每使用一次,都往乙個固定的容器中去註冊並且將使用過得物件進行快取,下次去取物件的時候,直接從快取中獲取,以保證每次獲取的都是同乙個物件,ioc中的單例模式就是典型的註冊登記式單例模式。
public enum regosterenum
}
借助jdk1.5中新增的列舉來實現單例模式。不僅能避免多執行緒同步問題,而且還能防止反序列化重新建立新的物件。
乙個單例的物件序列化之後再通過反序列化會重新生成乙個新的例項,破壞了單例模式。針對於這種情況可以採用重寫readresolve()方法避免此類問題發生。
/**
* 反序列化時導致單例破壞
*/public class seriable implements serializable
private static final seriable seriable = new seriable();
public static seriable getinstance()
private object readresolve()
}
設計模式 單例模式
單例模式 singleton pattern 是乙個比較簡單的模式,其定義如下 ensure a class has only one instance,and provide a golbal point of acess to it.確保某乙個類只有乙個例項,而且自行例項化並且向整個系統提供這個...
設計模式 單例模式
class testsingleton static public function instance return self testsingleton private function clone public function setsinvar sinvar public function ...
設計模式 單例模式
單例模式的目的是保證類在系統中只被例項化一次,由該唯一的例項來為系統提供服務.單例模式主要用於保證服務的統一,比如獲取統一的編號服務,模仿oracle的序列生成等.但單例的使用需要謹慎,特別是在需要作負載均衡的地方,因為這種程式級的單例模式實際上只能保證在乙個應用中為單例.如果被多個應用載入,還是會...