最近在看《劍指offer》這本書,也是被大家忽悠說是求職必看,可惜全書是基於C++/C#寫的,小生缺對Java比較感興趣,心想不如用Java實現以下書上的內容。
不好的解法一:只適用於單線程環境
public class Singleton1{
//把構造函數設爲私有以禁止他人創建實例
private Singleton1(){
}
private static Singleton1 instance = null;
public static Singleton1 getInstance(){
if(instance == null){
instance = new Singleton1();
}
return instance;
}
}
不好的解法二:雖然能在多線程環境中工作,但效率不高
public class Singleton2{
//把構造函數設爲私有以禁止他人創建實例
private Singleton2(){
}
private static Singleton2 instance = null;
//給getSingleton()方法加上同步鎖
public static synchronized Singleton2 getInstance(){
if(instance == null){
instance = new Singleton2();
}
return instance;
}
}
可行的解法:加同步鎖前後兩次判斷實例是否已存在
public class Singleton3{
//把構造函數設爲私有以禁止他人創建實例
private Singleton3(){
}
private static Singleton3 instance = null;
//給getSingleton()方法加上同步鎖
public static Singleton3 getInstance(){
//只是在實例還沒創建之前需要加鎖
if(instance == null){
synchronized(Singleton3.class){
if(instance == null){
instance = new Singleton3();
}
}
}
return instance;
}
}
推薦的解法:靜態內部類實現
public class Singleton4 {
//私有的靜態內部類,第一次調用時創建
//靜態內部類只會被加載一次,所以這種寫法也是線程安全的
private static class Holder {
private static Singleton4 instance = new Singleton4();
}
private Singleton4(){
}
public static Singleton4 getSingleton4(){
return Holder.instance;
}
}
以上就是《劍指offer》中提到的單例模式的實現方法,Java沒有靜態構造函數(只有靜態初始化塊)。
另外小生最近也在看《Effective Java》,第三條就提到了“用私有構造器或者枚舉類型強化Singleton屬性”,就是說還可以用final域和枚舉類型實現單例模式
final域方法:
public class Singleton5{
//把構造函數設爲私有以禁止他人創建實例
private Singleton5(){
}
//創建類的同時創建,天生是線程安全
private static final Singleton5 instance = new Singleton5();
public static Singleton5 getInstance(){
return instance;
}
}
枚舉類型方法:
public enum Singleton6{
INSTANCE;
}