其他設計模式
java單例模式
java建造者模式
java策略模式
java代理模式
java觀察者模式
java適配器模式
java外觀模式
定義
單例模式是用來保證這個類在運行期間只會被創(chuàng)建一個類實例,提供了一個全局唯一訪問這個類實例的訪問點。
實現(xiàn)
創(chuàng)建自己的唯一實例,構造方法私有化论巍,并提供一個getInstance的方法,讓外部來訪問這個類的唯一實例谭跨。
何時選用單例模式
當需要控制一個類的實例只能有一個匙监,而且用戶只能從一個全局訪問點訪問它時香伴,可以選用單例模式荧嵌。
1 餓漢式
public class Singleton {
// 加載該類時呛踊,單例就會被實例化
private static Singleton instance = new Singleton();
// 構造函數(shù) = 私有
// 原因:禁止他人創(chuàng)建實例
private Singleton() {
}
// 通過調(diào)用靜態(tài)方法獲得創(chuàng)建的單例
public static Singleton getInstance() {
return instance;
}
}
2 懶漢式
public class Singleton {
// 先賦值為Null砾淌,需要時才手動調(diào)用 getInstance() 創(chuàng)建
private static Singleton instance = null啦撮;
private Singleton() {
}
// 創(chuàng)建單例
public static Singleton getInstance() {
// 先判斷單例是否為空,以避免重復創(chuàng)建
if( instance == null){
instance = new Singleton();
}
return instance;
}
}
區(qū)別
1.餓漢式是典型的空間換時間,類加載時就已實例化
2.懶漢式是典型的時間換空間,調(diào)用時才實例化
3.不加同步的懶漢式是線程不安全的汪厨。比如赃春,有兩個線程,一個是線程A劫乱,一個是線程B织中,它們同時調(diào)用getInstance方法,就可能導致并發(fā)問題衷戈。
4.餓漢式是線程安全的狭吼,因為虛擬機保證只會裝載一次,在裝載類的時候是不會發(fā)生并發(fā)的殖妇。
如何實現(xiàn)懶漢式的線程安全刁笙?
雙重加鎖機制,指的是:進入方法過后,先檢查實例是否存在疲吸,如果不存在才進入下面的同步塊座每,這是第一重檢查。進入同步塊后摘悴,再次檢查實例是否存在峭梳,如果不存在,就在同步的情況下創(chuàng)建一個實例蹂喻。這是第二重檢查葱椭。
雙重加鎖機制的實現(xiàn)會使用一個關鍵字volatile,它的意思是:被volatile修飾的變量的值口四,將不會被本地線程緩存挫以,所有對該變量的讀寫都是直接操作共享內(nèi)存,從而確保多個線程能正確的處理該變量窃祝。
3 雙重檢查加鎖
public class Singleton {
/**
* 對保存實例的變量添加volitile的修飾
*/
private volatile static Singleton instance = null;
private Singleton(){
}
public static Singleton getInstance(){
//先檢查實例是否存在掐松,如果不存在才進入下面的同步塊
if(instance == null){
//同步塊,線程安全的創(chuàng)建實例
synchronized (Singleton.class) {
//再次檢查實例是否存在粪小,如果不存在才真正的創(chuàng)建實例
instance = new Singleton();
}
}
return instance;
}
}
4 一種更好的單例實現(xiàn)方式,靜態(tài)內(nèi)部類
public class Singleton {
/**
* 類級的內(nèi)部類大磺,也就是靜態(tài)類的成員式內(nèi)部類,該內(nèi)部類的實例與外部類的實例
* 沒有綁定關系探膊,而且只有被調(diào)用時才會裝載杠愧,從而實現(xiàn)了延遲加載
*/
private static class SingletonHolder{
/**
* 靜態(tài)初始化器,由JVM來保證線程安全
*/
private static Singleton instance = new Singleton();
}
/**
* 私有化構造方法
*/
private Singleton(){
}
public static Singleton getInstance(){
return SingletonHolder.instance;
}
}
5 枚舉方法
根據(jù)《Effective Java》中的說法逞壁,單元素的枚舉類型已經(jīng)成為實現(xiàn)Singleton的最佳方法流济。
public class EnumSingleton{
private EnumSingleton(){}
public static EnumSingleton getInstance(){
return Singleton.INSTANCE.getInstance();
}
private static enum Singleton{
INSTANCE;
private EnumSingleton singleton;
//JVM會保證此方法絕對只調(diào)用一次
private Singleton(){
singleton = new EnumSingleton();
}
public EnumSingleton getInstance(){
return singleton;
}
}
}