單例模式(Singletion)

單例模式(Singletion),我估計你們用到比較多.我使用的第一個設計模式就是單利模式.java

單例模式是爲了確保一個類有且僅有一個實例,併爲它提供一個全局訪問點.簡單說就是你不能new一個實例出來.設計模式


舉一個例子,好比在個人開發中有這樣一種狀況,咱們有同事寫了一組地圖工具MapUtils.java,咱們在不一樣的使用地方來調用這個工具類,爲了不有多個工具類實例存在就使用單利模式.安全

1、懶漢單利模式模式併發

public class MapUtils {

    private MKSearch           mkSearch;
    private LocationClient     locationClient;
    private OnLocationListener listener;

    private static MapUtils    instance;

    private MapUtils() {
    }

    public static MapUtils getInstance(Context context) {
        if (null == instance) {
            instance = new MapUtils(context.getApplicationContext());
        }
        return instance;
    }
}

構造函數爲private,這樣就不能使用new來建立實例.惟一實例只能經過getInstance()方法訪問。(事實上,經過Java反射機制是可以實例化構造方法爲private的類的,那基本上會使全部的Java單例實現失效。此問題在此處不作討論.)函數

上面的單例模式爲懶漢單例模式,懶漢式單例的實現沒有考慮線程安全問題,它是線程不安全的,併發環境下極可能出現多個MapUtils實例,要實現線程安全,有如下三種方式,都是對getInstance這個方法改造,保證了懶漢式單例的線程安全,若是你第一次接觸單例模式,對線程安全不是很瞭解,能夠先跳過下面這三小條,去看餓漢式單例,等看完後面再回頭考慮線程安全的問題.工具

一、在getInstance方法上加同步學習

public static synchronized MapUtils getInstance(Context context) {  
	if (null == instance) {    
	    instance = new MapUtils(context.getApplicationContext());
	}    
	return instance;  
}

二、雙重檢查鎖定線程

public static MapUtils getInstance(Context context) {
    if (null == instance) {
        synchronized (MapUtils.class) {
            if (null == instance) {
                instance = new MapUtils(context.getApplicationContext());
            }
        }
    }
    return instance;
}

三、靜態內部類設計

public class MapUtils {
    private static class LazyHolder {
        private static Context context;
        private static final MapUtils INSTANCE = new MapUtils(context.getApplicationContext());
    }
    private MapUtils(Context context){}
    public static final MapUtils getInstance(Context context) {
        LazyHolder.context = context;
        return LazyHolder.INSTANCE;
    }
}

2、餓漢式單例模式code

//餓漢式單例類.在類初始化時,已經自行實例化

public class MapUtils {  
    private MapUtils() {}  
    private static final MapUtils instance = new MapUtils();  
    //靜態工廠方法   
    public static MapUtils getInstance() {  
        return instance;  
    }  
}

餓漢式在類建立的同時就已經建立好一個靜態的對象供系統使用,之後再也不改變,因此天生是線程安全的。 還有一種登記式單例模式.沒有細細去看就不作介紹了.


什麼是線程安全? 若是你的代碼所在的進程中有多個線程在同時運行,而這些線程可能會同時運行這段代碼。若是每次運行結果和單線程運行的結果是同樣的,並且其餘的變量的值也和預期的是同樣的,就是線程安全的。 或者說:一個類或者程序所提供的接口對於線程來講是原子操做,或者多個線程之間的切換不會致使該接口的執行結果存在二義性,也就是說咱們不用考慮同步的問題,那就是線程安全的。


PS:對於設計模式我只是做爲學習筆記來寫的,並不是網上大牛們的手筆,因此各位看官看看就行,有錯誤請多多指正,要真正學習設計模式,書籍有,《大話設計模式》,這個須要C++語言底子,《您的設計模式》這個講解的頗有風趣,沒有《大話設計模式》講解的深,還有一本《Head First 設計模式》也講解的蠻有意思的。

相關文章
相關標籤/搜索