單例模式

單例模式一定要扛得住并發(fā)。


單例模式有很多版本,包括雙重檢查,靜態(tài)內(nèi)部類(lèi),枚舉,其他的寫(xiě)法也有,建議大家看深入淺出單實(shí)例SINGLETON設(shè)計(jì)模式

餓漢單例的話(huà)太一勞永逸,如果你碰上了那種要使用很多資源的類(lèi)的單例,但是一時(shí)半會(huì)兒又用不上的情況,那么還是不要用了。我寫(xiě)的單例都是使用的時(shí)候才加載的那種,也就是所謂的懶漢式單例。

單例模式的特點(diǎn)總結(jié)為兩私有一公開(kāi),隨時(shí)注意靜態(tài)(我認(rèn)為是兩處?kù)o態(tài)),兩私有是指私有構(gòu)造方法,私有的指向自身的實(shí)例一公開(kāi)是指公開(kāi)的對(duì)外獲取單例的方法,隨時(shí)注意靜態(tài)是指:因?yàn)闃?gòu)造方法私有,所以你不能通過(guò)創(chuàng)建實(shí)例來(lái)調(diào)用方法,那么就只有通過(guò)類(lèi)名來(lái)調(diào)用里面的靜態(tài)方法,記憶的鏈?zhǔn)剿季S是這樣的,獲取單例的方法必須靜態(tài),這個(gè)方法要調(diào)用指向單例的實(shí)例,由于靜態(tài)方法只能調(diào)用靜態(tài)方法和靜態(tài)變量,那么被調(diào)用的那個(gè)單例的實(shí)例也必須是靜態(tài)的(多注意枚舉那里)。

基本的模板
class Singleton {
    private Singleton(){}
    private static Singleton singleton = null;
    public static Singleton getSingleton() {
        return null;
    }
}
具體的實(shí)現(xiàn)

/**
 * Double check && volatile Edition
 * 雙重檢查volatile版本
 */
class DoubleCheckSingleton {
    private DoubleCheckSingleton(){}
    private static volatile DoubleCheckSingleton INSTANCE = null;
    public static DoubleCheckSingleton getSingleton() {
        if (INSTANCE == null) {
            synchronized (DoubleCheckSingleton.class) {
                if (INSTANCE == null) {
                    INSTANCE = new DoubleCheckSingleton();
                }
            }
        }
        return  INSTANCE;
    }
}

/**
 * Static inner class Edition
 * 靜態(tài)內(nèi)部類(lèi)版本
 */
class InnerClassSingleton {
    private InnerClassSingleton(){}

    private static class SingletonHolder {
        private static final InnerClassSingleton INSTANCE = new InnerClassSingleton();
    }

    public static InnerClassSingleton getSingleton() {
        return SingletonHolder.INSTANCE;
    }
}

/**
 * Enum Edition
 * 枚舉版本
 */
class EnumSingleton {
    private EnumSingleton(){}

    public static EnumSingleton getSingleton() {
        return singleton.INSTANCE.getSingleton();
    }

    enum singleton {
        INSTANCE;
        private EnumSingleton singleton;
        private singleton(){ singleton = new EnumSingleton();}
        private EnumSingleton getSingleton(){return singleton;}
    }
}

/**
 * 測(cè)試線(xiàn)程,在這里更改使用的版本,雖然這很不軟件工程
 */
class SimpleThread implements Runnable {
    @Override
    public void run() {
        System.out.println(DoubleCheckSingleton.getSingleton());
    }
}

/**
 * 測(cè)試主入口
 */
public class SingletonVersions {
    public static void main(String[] args) {
        SimpleThread simpleThread = new SimpleThread();
        for (int i = 0; i < 100; i++) {
            Thread thread = new Thread(simpleThread);
            thread.start();
        }
    }
}

不知道大家注意到了沒(méi)有,我這里這么多個(gè)類(lèi),就SingletonVersions是public的,而且這么多個(gè)代碼全在一個(gè)文件也就是SingletonVersions.java里面,沒(méi)錯(cuò),但是大家注意,訪(fǎng)問(wèn)權(quán)限,沒(méi)有寫(xiě)public的類(lèi)只具有包訪(fǎng)問(wèn)權(quán)限。一個(gè)java文件里面只準(zhǔn)存在一個(gè)public的類(lèi),但是還可以寫(xiě)其他的非public類(lèi),還可以寫(xiě)接口,枚舉,我經(jīng)常因?yàn)榇a很短,圖方便的話(huà)就寫(xiě)在一個(gè)類(lèi)里面了。


泛型單例

這個(gè)提的人很少,但是是有他的存在價(jià)值的,比如你有很多個(gè)工具類(lèi),都想用單例模式來(lái)創(chuàng)建唯一對(duì)象來(lái)減小開(kāi)銷(xiāo),那么寫(xiě)個(gè)泛型就是有必要了的。

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by Curry on 17/6/26.
 */

public class Singleton<T> {

    /**
     * 私有構(gòu)造函數(shù),在這里顯得表雞肋,沒(méi)有任何作用
     * 但是處于對(duì)單例模式的尊重,要給全它定義中的,私有構(gòu)造函數(shù)、私有靜態(tài)自身實(shí)例,共有靜態(tài)的獲取單例的方法
     */
    private Singleton() {
    }

    /**
     * 私有,靜態(tài),并發(fā)哈希表,用于存儲(chǔ)所有的實(shí)例的唯一單例,而且其本身也是靜態(tài)唯一的
     */
    private static ConcurrentHashMap<Class, Object> map = new ConcurrentHashMap<>();

    /**
     * 公開(kāi),靜態(tài),泛型的獲取對(duì)應(yīng)類(lèi)型的單例
     */
    public static <T> T getDefault(Class<T> type) {
        if (map.get(type) == null) {
            synchronized (map) {
                if (map.get(type) == null) {
                    try {
                        /**
                         * 這里利用反射,將私有的構(gòu)造方法改為共有的,用于創(chuàng)建實(shí)例,否則無(wú)法創(chuàng)建實(shí)例
                          */
                        Constructor constructor = type.getDeclaredConstructor();
                        constructor.setAccessible(true);
                        map.put(type, constructor.newInstance());
                    } catch (NoSuchMethodException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InstantiationException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return (T)map.get(type);

    }

    /**
     * 根據(jù)類(lèi)型移除存儲(chǔ)在哈希表中的單例
     */
    public static <T> void removeSingleton(Class<T> type) {
        map.remove(type);
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容