2012-11-20 18 views
3

我有幾個擴展父類的子類,被迫擁有一個統一的構造函數。我有一個隊列,它保存了這些類的列表,它們必須擴展MergeHeuristic。我目前擁有的代碼如下所示:任何方式來簡化這與動態類實例化的形式?

Class<? extends MergeHeuristic> heuristicRequest = _heuristicQueue.pop(); 
    MergeHeuristic heuristic = null;  

    if(heuristicRequest == AdjacentMACs.class) 
     heuristic = new AdjacentMACs(_parent); 
    if(heuristicRequest == SimilarInterfaceNames.class) 
     heuristic = new SimilarInterfaceNames(_parent); 
    if(heuristicRequest == SameMAC.class) 
     heuristic = new SameMAC(_parent); 

有什麼方法來簡化動態實例化類,沿着線的東西:

heuristic = new heuristicRequest.somethingSpecial(); 

這將壓平的該塊如果聲明。

+0

@jlordo不,他們不會,'heuristicRequest'是'Class'對象。 – Brian

+0

sry,我的眼睛比我的大腦快:D – jlordo

回答

3

它看起來像你使用隊列作爲一種標誌,該類指示實例是什麼類型的請求。不使用反射另一種方法是使該標誌的行爲明確通過引入一個枚舉指示請求類型,有工廠方法:

public enum HeuristicType { 

    AdjacentMACsHeuristic(AdjacentMACs.class) { 
    @Override public MergeHeuristic newHeuristic(ParentClass parent) { 
     return new AdjacentMACs(parent); 
    } 
    }, 
    SimilarInterfaceNamesHeuristic(SimilarInterfaceNames.class) { 
    @Override public MergeHeuristic newHeuristic(ParentClass parent) { 
     return new SimilarInterfaceNames(parent); 
    } 
    }, 
    ... // other types here. 
    ; 

    private final Class<? extends MergeHeuristic> heuristicClass; 
    public Class<? extends MergeHeuristic> getHeuristicClass() { 
    return heuristicClass; 
    } 

    abstract public MergeHeuristic newHeuristic(ParentClass parent); 

    private HeuristicType(Class<? extends MergeHeuristic> klass) { 
    this.heuristicClass = klass; 
    } 

} 

你的客戶端代碼就變成了:

Queue<HeuristicType> _heuristicQueue = ... 
HeuristicType heuristicRequest = _heuristicQueue.pop(); 
MergeHeuristic heuristic = heuristicRequest.newHeuristic(_parent); 

使用枚舉而不是反射的主要優點是:

  • 您明確指出添加新的啓發式類型的要求,即必須存在啓發式類和th在你必須能夠基於父母來實例化它。
  • 您在系統中有一個單點,您可以看到所有可用的啓發式類型。
  • 通過將實例化抽象爲工廠方法,您允許交替構造函數簽名的可能性。
+0

你的代碼有幾個問題,但這個想法還是不錯的。順便說一句,我不知道你可以在枚舉中聲明'abstract'方法,所以非常感謝你給我一些新的東西。將最後一個枚舉聲明後的'''改爲';',並將構造函數更改爲'private',它應該可以正常工作。 – Brian

+0

感謝您指出 - 意味着留下一個佔位符額外的枚舉聲明,但忘記了。 – Alex

+0

好的,沒問題,+1 – Brian

1

不幸的是,你不能強制一個類有一個特定的構造函數或一個靜態方法 - 兩者對你的情況都非常有用。

由於所有建設者採取同樣的說法有一個其他方式使用動態類的實例,以簡化代碼:

Constructor c = heuristicRequest.getConstructor(ParentClass.class). 
heuristic = c.newInstance(_parent); 

請注意,您的代碼不包含_parent的類類型 - 在代碼示例我將其命名爲ParentClass.class - 您必須將其適用於您的代碼。

+1

爲什麼不使用參數化的'Constructor'?除非您投射新實例,否則您的代碼將無法使用。 – Brian

+0

你說得對 - 你的方式更優雅。無論如何,我不明白爲什麼這可能是某人downvote這個工作解決方案的原因... – Robert

2

你可以使用反射,但它不會使代碼更漂亮。

try { 
    Constructor<? extends MergeHeuristic> heuristicConstructor = 
      heuristicRequest.getConstructor(_parent.getClass()); 
    heuristic = heuristicConstructor.newInstance(_parent); 
} catch (Exception ex) { 
    // TODO Handle this 
} 

只有在你打算有很多不同的類時才這樣做。不要擔心,如果它只是其中的3個,那麼你的代碼就很好。

+0

_parent是一個類 - 無需調用getClass()就可以了。 – Robert

+0

OP沒有說'_parent'是一個類,對我來說看起來像一個局部變量,它不可能是'Class _parent'。你可以在你自己的回答中說,「請注意,你的代碼不包含_parent的類類型...」。使用'getClass'只是另一種方式,而且更通用一些。我不得不測試它是否可以正確地用於參數類型的子類,但是如果OP在該特定行中存在問題,則不難評論答案並向我提問。 – Brian

0

Class.forName(heuristicRequest.getName())的一個選項嗎?

然後constructor heuristicRequestClass.getDeclaredConstructor(_parent.getClass());

heuristic = constructor.newInstance(_parent);

+1

他已經有了班,爲什麼他需要再次得到它? – Brian

+0

是的。在我的答案答案中跳過第一行。 +1上面的答案。 – Sormuras