Java【設計模式】單例模式七種實現方式(附源碼)

單例模式介紹

所謂類的單例模式設計,就是採起必定的方法保證在整個系統中,對某個類只能存在一個對象實例,而且該類只提供一個取得其對象實例的方法(靜態)java

單例模式經常使用實現方式

餓漢式

步驟以下:安全

  1. 構造方法私有化
  2. 類內建立對象(建立就進行實例化)
  3. 向外提供一個靜態公共方法
public class SingletonTest01 { 
	public static void main(String[] args) { 
		Singleton st=Singleton.getInstance();//類裝載時便進行實例化
		Singleton st2=Singleton.getInstance();
		System.out.println(st==st2);
		System.out.println(st.hashCode());
		System.out.println(st2.hashCode());
	}
}
class Singleton{ 
	
	//餓漢式
	//1.構造器私有化
	private Singleton()
	{ 
	}
	//2.本類內部建立對象實例
	private final static Singleton instance =new Singleton();
	//3。提供一個公有靜態方法
	public static Singleton getInstance()
	{ 
		return instance;
	}
}

優勢:線程安全(實現同步)
缺點:傳參數困難,且容易形成內存浪費(裝載即實例,可是有可能用不到)
多線程

懶漢式

步驟以下:spa

  1. 構造方法私有化
  2. 類內建立對象
  3. 向外提供一個靜態公共方法(須要判斷是否非空)
public class SingletonTest03 { 
	public static void main(String[] args) { 
		System.out.println("線程不安全!!!!");
		Singleton st=Singleton.getInstance();//類裝載時便進行實例化
		Singleton st2=Singleton.getInstance();
		System.out.println(st==st2);
		System.out.println(st.hashCode());
		System.out.println(st2.hashCode());
	}
}
class Singleton{ 
	private static Singleton instance;
	private Singleton()
	{ 
	}
	public static Singleton getInstance()
	{ 
		if(instance==null)
			instance=new Singleton();
		return instance;
	}
	
}

優勢:延遲加載
缺點:線程不安全(多線程下,若一個線程進入了if(singleton==null)判斷語句塊,還將來得及往下執行,另外一個線程也經過了這個判斷語句,這時便會產生多個實例)
線程

同步方法

synchronized同步方法,每一次只容許一個線程訪問。設計

public class SingletonTest04 { 
	public static void main(String[] args) { 
		Singleton st=Singleton.getInstance();
		Singleton st2=Singleton.getInstance();
		System.out.println(st==st2);
		System.out.println(st.hashCode());
		System.out.println(st2.hashCode());
	}

}
class Singleton{ 
	private static Singleton instance;
	private Singleton()
	{ 
		
	}
	public static synchronized Singleton getInstance()
	{ 
		//此方法效率低下
		if(instance==null)
			instance=new Singleton();
		return instance;
	}
}

優勢:解決了線程不安全的問題
缺點:效率過低(每一個線程在想得到類的實例的時候,執行getInstance()方法都要進行同步。其實只執行一次代碼實例化就足夠了。)
code

同步代碼塊
class Singleton
{ 
	private static Singleton instance;
	private Singleton()
	{ 
		
	}
	public static Singleton getInstance()
	{ 
		if(instance==null)
		{ 
			synchronized(Singleton.class)
			{ 
				instance=new Singleton();
			}
		}
		return instance;
	}
}

寫法錯誤,同步並不能起到真正的做用,實際開發不可用。對象

雙重檢查
class Singleton{ 
	private static volatile Singleton instance;
	private Singleton()
	{ 
		
	}
	public static synchronized Singleton getInstance()
	{ 
		if(instance==null)//解決了效率低下
		{ 
			synchronized(Singleton.class)
			{ 
				if(instance==null)//雙重檢查,實現一次實例化
				{ 
					instance=new Singleton();
				}
			}
		}
		return instance;
	}
}

實現了延時加載,與線程安全,同時保證了效率。內存

靜態內部類

class Singleton
{ 
	private static volatile Singleton instance;
	private Singleton()
	{ 
	}
	//外類裝載不會立刻裝載的
	private static class SingletonInstance{ 
		private static final Singleton Instance=new Singleton();//餓漢式
	}
	//用到他的時候才裝載(JVM裝載時線程安全)
	public static synchronized Singleton getInstance()
	{ 
		return SingletonInstance.Instance;//懶漢式
	}
}

優勢:開發

  1. 這種方法採用了類裝載的機制來保證初始化實例時只有一個線程。
  2. 靜態內部類在Singleton進行裝載時並不會當即實例化,而是在須要進行實例化時,調用getInstance()方法,纔會裝載SingletonInstance類,從而完成實例化。
  3. 類的靜態屬性只會在第一次加載類的時候初始化,JVM保證了線程的安全,在類進行初始化時,別的線程是沒法進入的。
    這種方法也實現了延時加載與線程安全

枚舉方式

public class SingletonTest08 { 
	public static void main(String[] args) { 
		Singleton st=Singleton.Instance;
		Singleton st2=Singleton.Instance;
		System.out.println(st==st2);
		System.out.println(st.hashCode());
		System.out.println(st2.hashCode());
	}

}
enum Singleton{ //枚舉實現單利
	Instance;//屬性
	public void sayOK()
	{ 
		System.out.println("ok~");
	}
}

優勢: 枚舉方式實現單例,不只可以避免多線程同步問題,並且還能防止反序列化從新建立新的對象。

相關文章
相關標籤/搜索