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