單例用的就比較多並且廣了,說的是 某個單例類,只在內存中創建唯一一個實例,比如android中application,只有一個實例,只初始化一次,又比如window的資源管理器,不管你開多少個,永遠只有一個在運行。好處是節省資源,尤其是對於頻繁訪問的類。
要寫單例模式,我認爲最重要的是什麼時候實例化這個類,有以下幾種可以:
1.類初始化就產生實例
2.在方法裏面寫,類初始化實例化,在調用方法才實例化
那麼單例的創建方式有4中(其實是5種,只不過有一種因爲不推薦使用,就不學習了),這種寫法分類來自尚學堂的老師。
餓漢法:
這個寫法是類在初始化就已經完成單例的創建的,不可以延遲操作
package SinglePattern;
/**
* 這是類初始化就馬上加載,惡漢
* @author cloudhuan
*
*/
public class SinglePattern02 {
//這裏類初始化都是線程安全的
private static final SinglePattern02 PATTERN02 = new SinglePattern02();
private SinglePattern02(){};
public static SinglePattern02 getInstance(){
return PATTERN02;
}
}
懶漢法:
這個可以實現延遲加載,但是對於多線程來說效率是最低的,因爲有一個synchronized 同步鎖,創建過程可能會等待。
package SinglePattern;
/**
* 這個可以延遲加載,真正使用的時候纔去加載,懶漢
* 類加載都是線程安全的,但是這裏需要加同步鎖
* @author cloudhuan
*
*/
public class SingleInstance01 {
public static SingleInstance01 singleInstance;
//可能有多個方法去用,所以要同步,不加可能還是會造成多個對象
public static synchronized SingleInstance01 getInstance(){
if(singleInstance == null){
return new SingleInstance01();
}
return singleInstance;
}
public void printHello(){
System.out.println("hello");
}
}
靜態內部類法:
是最推薦的寫法,把實例化放在靜態內部類裏面,在有需要纔會加載內部類,並且類初始化是天然同步的。
package SinglePattern;
/**
* 靜態內部類的加載方式,用的最多的,集合懶漢和惡漢的優點
* 1.類加載是天然線程安全的
* 2.用到才加載
* @author cloudhuan
*
*/
public class SinglePattern03 {
private static class SingleInst{
private static SinglePattern03 pattern03 = new SinglePattern03();
}
private SinglePattern03(){}
public static SinglePattern03 getInstance(){
return SingleInst.pattern03;
}
}
枚舉法:
當不需要延遲加載就用這個吧,因爲枚舉類型是系統自帶的單例模式,沒有什麼BUG,寫法也是超級簡單的
package SinglePattern;
/**
* 這是通過枚舉方式的,枚舉的類型就是系統自帶的單例模式
* @author cloudhuan
*
*/
public enum SinglePattern04 {
INSTANCE("aaa");
SinglePattern04(String str){
System.out.println(str);
}
}
上面四種方式,推薦的是枚舉和靜態內部類模式,效率最高。