2015-02-05 35 views
1

我正在開發一個工廠,它可以通過使用Class參數實例化類型爲Objects的對象。該工廠的代碼是:ObjectFactory與<?>參數

public static final class AbilityFactory { 
    private AbilityFactory(){} 

    public static <T extends Class<A>, A extends Ability> A getAbility(T clazz){ 
     A ability = null; 
     try{ 
      ability = clazz.newInstance(); 
     } catch(InstantiationException | IllegalAccessException ex){ 
      ex.printStackTrace(); 
     } 
     return ability; 
    } 
} 

客戶端代碼是類似的東西:

Ability.AbilityFactory.getAbility(Firebolt.class)); 

我想通這個設計唯一的問題是,能力類是抽象,你可以通過類似這樣的:

Ability.AbilityFactory.getAbility(Ability.class)); 

導致java.lang.InstantiationException

我想知道我是否可以像「?extends Ability but Ability」那樣做一些約束,或者它只是一個糟糕的設計,我應該把例如Enum作爲參數傳遞到工廠的方法中以防止出現這種情況。

+1

我不明白爲什麼這會是一個問題,只是不要傳遞Ability.class作爲參數。 – FINDarkside 2015-02-05 15:53:10

+1

如果你所有的'Ability'子類都有一個默認的構造函數,並且你需要'Class'對象來使用這個工廠來實例化它,那麼有什麼意義呢?爲什麼不使用新的操作符,並避免反射? – 2015-02-05 15:53:14

+0

@FINDarkside好,那麼泛型的全部用途正在消失。在編譯時你不能確定一個錯誤的參數。 – Zarial 2015-02-05 15:58:17

回答

2

您唯一能做的就是提供一個標記界面,比如ConcreteAbility並且有<T extends Ability & ConcreteAbility>。然後你需要用所有具體的能力來實現ConcreteAbility。

+0

這似乎是一個很好的建議,但現在我無法將有限的論據傳遞給我的Champion的構造函數。之前它是** public Champion(Class <?extends Ability > firstAbility){...} **並且在我按照您的建議修改了我的工廠之後:** public static ,擴展Ability&ConcreteAbility>一個getAbility(T clazz){...} **我需要在我的構造函數中類似** Class <?擴展能力&ConcreteAbility> **,但這不是一個選項,因爲語法錯誤。你能告訴我一些解決方法嗎? – Zarial 2015-02-05 16:20:10

+1

嗯,它真的幫了我。我忘了我們也可以在構造函數中使用命名的類型參數。謝謝!)我的構造函數的代碼現在是:** public ,A extends Ability&ConcreteAbility> Champion(T firstAbility,T secondAbility){...} ** – Zarial 2015-02-05 16:31:26

+1

Btw。你不需要T,除非你真的擁有你自己的類實現 - 看到'java.lang.Class'是最終的,這是不太可能的。因此,您的構造函數可以簡化爲'public Champion( firstAbility ...)' – llogiq 2015-02-05 16:49:34