1. 程式人生 > >1.單例設計模式(懶漢式,餓漢式,列舉式,雙重檢測鎖式,靜態內部類式)

1.單例設計模式(懶漢式,餓漢式,列舉式,雙重檢測鎖式,靜態內部類式)

設計模式分類:
1:建立型模式:
單例模式,工廠模式,抽象工廠模式,建造者模式,原型模式;
2:結構型模式:
介面卡模式,橋接模式,裝飾模式,組合模式,外觀模式,享元模式,代理模式
3:行為型模式:
模板方法模式,命令模式,迭代器模式,觀察者模式,中介者模式,備忘錄模式,
直譯器模式,狀態模式,策略模式,職責鏈模式,訪問者模式。

單例模式應用場景:
windows的task manager(工作管理員)就是很典型的單例模式,
windows的recycle bin(回收站)也是典型的單例應用,在整個系統執行過程中,回收站一直
維護僅有的一個例項。
專案中,讀取配置檔案的類,一般也只有一個物件,沒有必要每次使用配置檔案資料,每次
new一個物件去讀取,
應用程式的日誌應用,一般都可用單例模式實現,這一般是由於共享的日誌檔案一直處於開啟狀態,因為
只能有一個例項去操作,否則內容不好追加。
資料庫連線池的設計一般也是採用單例模式,因為資料庫連線是一種資料庫資源
作業系統的檔案系統,也是大的單例模式實現的具體例子,一個作業系統只能有一個檔案系統
Application也是單例的典型應用(servlet程式設計中會涉及到)
在spring中,每個bean預設就是單例的,這樣做的優點是spring容器可以管理
在servlet程式設計中,每個servlet也是單例
在spring mvc框架/struts1框架中,控制器物件也是單例

單例模式的實現(5種)
常用:
餓漢式(執行緒安全,呼叫效率高,但是不能延時載入)
懶漢式(執行緒安全,呼叫效率不高,可以延時載入)
其他:
雙重檢測鎖式(由於jvm底層內部模型原因,偶爾會出問題,不建立使用)
靜態內部類式(執行緒安全,呼叫效率高,但是可以延時載入)
列舉單例(執行緒安全,呼叫效率高,不能延時載入)

常用惡漢式,懶漢式:

/**
 * 測試惡漢式單例模式
 * @author Administrator
 *
 */
public class SingleTonDemo1 {
	
	//類初始化時,立即載入物件。天然的執行緒安全的
	private static SingleTonDemo1 instance = new SingleTonDemo1(); //類初始化時,立即載入
	
	private SingleTonDemo1() {
		
	}
	
	//方法沒有同步,呼叫效率高
	public static SingleTonDemo1 getInstance() {
		return instance;
	}
}
/**
 * 測試懶漢式單例模式
 * @author Administrator
 *
 */
public class SingleTonDemo2 {
	
	private static SingleTonDemo2 instance = null;
	
	private SingleTonDemo2() {
		
	}
	
	//方法使用同步,呼叫效率低
	public static synchronized SingleTonDemo2 getInstance() {
		if(instance == null) {
			instance = new SingleTonDemo2();
		}
		return instance;
	}
	
}
/**
 * 列舉單例模式
 * @author Administrator
 *
 */
public enum SingleTonDemo4 {
	INSTANCE; //雖然只有一行
}
public class TestEnum {
	
	//測試列舉單例
	public static void main(String[] args) {
		SingleTonDemo4 instance1 = SingleTonDemo4.INSTANCE;
		SingleTonDemo4 instance2 = SingleTonDemo4.INSTANCE;
		SingleTonDemo4 instance3 = SingleTonDemo4.INSTANCE;
		
		System.out.println(instance1 == instance3);
	}
	
}
/**
 * 靜態內部類式單例設計模式
 * @author Administrator
 *
 */
public class SingleTonDemo3 {
	
	//只會被載入一次,執行緒安全
	static class Nested {
		private  static SingleTonDemo3 instance = new SingleTonDemo3();
	}
	
	private SingleTonDemo3() {
		
	}
	
	public static SingleTonDemo3 getInstance() {
		return Nested.instance;
	}
}
<p>/**
 * 雙重檢測鎖式單例設計模式
 * @author Administrator
 *
 */
public class SingleTonDemo5 {</p><p>    private static volatile SingleTonDemo5 instance;
   
    private SingleTonDemo5() {
     
    }
 
    //getInstance()方法檢查了兩次來判斷INSTANCE是否為null,這就是為什麼叫雙檢索的原因,
    //記住雙檢索在java5之前是有問題的,但是java5在記憶體模型中有了volatile變數之後就沒問題了
    public static SingleTonDemo5 getInstance(){
        if(instance == null){
           synchronized(SingleTonDemo5.class){
               if(instance == null){
                instance = new SingleTonDemo5();
               }
           }
        }
        return instance;
    }
    
}</p>