簡體   English   中英

Java對單例的引用映射

[英]Java Map of References to Singletons

我想創建一個單例類的映射,我可以通過交叉引用訪問該映射以響應特定的請求。 我已經實現了以下內容,但是無法獲取可以調用getInstance()的實際引用。

Map<Integer, Class<? extends Thing>> xref = new HashMap<Integer, Class<? extends Thing>>();
xref.put(1, ThingOne.class);
xref.put(2, ThingTwo.class);

Class<? extends Thing> t = xref.get(1);

最終再做類似...

something.perform(arg1, arg2);

無法弄清楚如何從“ t”轉換為“ something”,或者如果按照我的編碼方式,這是否可行。 我嘗試調用.cast(Thing.class).getInstance(),但遇到了Cast異常。 還嘗試了反射以獲得getInstance()方法,但是那里也沒有運氣。

可能是我完全走錯了路。 給定1..n種可能的功能,該解決方案的任何給定實例可能只需要其中的一個子集。 另外,我想輕松地添加/刪除類,並在啟動時通過config和一堆對象實例化來管理接口。

謝謝!!!

我不太了解您創建此地圖的目的。 從您編寫的內容來看,您似乎可以簡單地將靜態的getInstance()方法(返回單例)放在每個相關的類上。 或更瑣碎的是:將每個共享實例作為其類的靜態final字段。

如果必須使用地圖,請不要使用整數作為鍵。 類是鍵,其實例是值。 就像是:

private static final Map<Class<?>,Object> singletons = new HashMap<>();

public static synchronized <T> T getSingleton(Class<T> klass) {
    Object obj = singletons.get(klass);
    if (obj == null) {
        try {
            obj = klass.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        singletons.put(klass, obj);
    }
    return klass.cast(obj);
}

那里的創建代碼很棘手,需要一個公共的無參數構造函數。 您也可以通過反射在每個類上調用一個靜態的,專門命名的方法來創建所需的實例(“ createInstance”),該實例可能會更靈活一些,但是當您這樣做時,它再次詢問為什么要打擾地圖,什么時候可以直接在類上調用方法?

映射的一種有趣的可能性是提供創建實例的功能。 使用Java 8語法(導入java.util.function.Supplier ):

private static final Map<Class<?>,Object> singletons = new HashMap<>();

public static synchronized <T> T getSingleton(Class<T> klass) {
    Object obj = singletons.get(klass);
    if (obj instanceof Supplier) {
        obj = ((Supplier<?>)obj).get();
        singletons.put(klass, obj);
    }
    return klass.cast(obj);
}

public static synchronized <T> void declareSingleton(Class<T> klass, Supplier<T> supplier) {
    if (Supplier.class.isAssignableFrom(klass)) {
        // prevent Supplier<Supplier<?>> weirdness;
        // could use separate maps if those are really needed
        throw new UnsupportedOperationException();
    }
    singletons.put(klass, supplier);
}

static {
    // add creation expressions for several classes;
    // instances will not be created until needed
    declareSingleton(ThingOne.class, () -> new ThingOne());
    declareSingleton(ThingTwo.class, () -> new ThingTwo(123));
}

我不確定這是否是您想要的,但其中可能包含一些想法。

編輯:我剛剛意識到使用類本身作為鍵的問題:即使在特定程序運行期間不需要類,它也會導致類被加載。 使用String鍵可以避免加載不需要的類,但會增加脆弱性。 這是反對將地圖用於所有這些的另一個論點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM