接觸學生的時候,總是在說設計模式很重要,至少應該知道幾種設計模式?
但是,也是給大家簡簡單單的介紹了幾種!
設計模式就是讓自己的代碼更加完善,更加健壯
第一種方案:懶漢式
懶漢式的類的實例創建是在getInstance方法中,懶漢式是典型的時間換空間,也就是每次獲取實例都會進行判斷,看是否需要創建實例,浪費判斷的時間。
當然,如果一直沒人使用的話,那就不會創建實例,則節約內存空間
package 單例模式;
/**
* 懶漢式
* @author 胖先森
*
*/
public class Singleton1 {
private static Singleton1 uniqueInstance = null;
private Singleton1(){}
public static synchronized Singleton1 getInstance(){
if(uniqueInstance == null){
uniqueInstance = new Singleton1();
}
return uniqueInstance;
}
}
這種懶漢式不加同步,所以是線程不安全的,可以加上synchornized使得線程安全
加入同步之后代碼為:public static synchronized Singleton getInstance(){}
但是這樣會降低整個訪問的速度,而且每次都要判斷,可以使用“雙重檢查加鎖”使得即線程安全,又能使性能不受到很大的影響。
“雙重檢查加鎖”是指并不是每次進入getInstance方法都需要同步,而是先不同步,進入方法過后,先檢查實例是否存在,如果不存在才進入下面的同步塊,這是第一重檢查,進入同步塊過后,再次檢查實例是否存在,不過不存在,就在同步的情況下創建一個實例,這是第二重檢查。這樣一來,就只需要同步一次了,從而減少了多次在同步的情況下進行判斷所浪費的時間,實現如下:
package 單例模式;
/**
* 雙重加鎖懶漢式
* @author Administrator
*
*/
public class Singleton3 {
private volatile static Singleton3 instance = null;
private Singleton3(){}
public static Singleton3 getInstance(){
if(instance == null){
synchronized (Singleton3.class) {
if(instance == null){
instance = new Singleton3();
}
}
}
return instance;
}
}
第二種方案:餓漢式
在課堂就是講了這種方式,我們再來看看
餓漢式是典型的空間換時間,當類加載的時候就會創建類實例,不管你用不用,先創建出來,然后每次電泳的時候,就不需要再判斷了,節省了運行時間,餓漢式是線程安全的
package 單例模式;
/**
* 餓漢式
* @author 胖先森
*
*/
public class Singleton2 {
private static Singleton2 uniqueInstance= new Singleton2();
private Singleton2(){}
public static Singleton2 getInstance(){
return uniqueInstance;
}
}
內部類實現方式
上面兩種方案都有一定的缺陷,那么有沒有一種方法既能夠實現延遲加載,又能夠實現線程安全呢?
要想實現線程安全,可以采用靜態初始化器的方式,它可以由JVM來保證線程的安全性,例如前面的餓漢式,但這樣一來,會浪費一定的空間。
如果有一種方法能夠讓類裝載的時候不去初始化對象,不就解決問題了嗎?一種可行的方法就是采用內部類,在這個內部類里面去創建對象實例,這樣一來,只要不實用到這個類級內部類,就不會創建對象實例,從而同時實現延遲加載和線程安全。
package 單例模式;
/**
* 使用內部靜態類,線程安全且高效
* @author 胖先森
*
*/
public class Singleton4 {
private static class SingletonHolder{
private static Singleton4 instance = new Singleton4();
}
private Singleton4(){
}
public static Singleton4 getInstance(){
return SingletonHolder.instance;
}
}
參考內容:單例模式的七種寫法