2012-09-04 23 views
4

我想嘗試工廠模式,並能夠實現它,但當產生超過幾個類的
,我認爲這將是醜陋的!所以任何的清晰度或建議將非常感激......如何確定工廠模式中的子類類型,而不是使用if else和switch?

我的超類:

public abstract class Output { 

    public abstract void generate(Data dat); } 

我得到了我從輸出擴展其他類,如

public class generateXML extends Output{ 
. 
. 
. 
} 

我的問題是有關在這裏:

public class generatorFactory(){ 

public Output generate(String str){ 

//或獲得一個對象作爲參數,如(Object obj)

if(str.equals("xml"){ 
return new generateXML(); 
} 
else if......... 
...... 
} 

有沒有什麼辦法可以確定子類型避免檢查每種類型?

回答

1

可以使用的newInstance()來實例化一個發電機,其類名你從參建:

public Generator getGenerator (final String type) 
{ 
    final Class generatorClass = ClassLoader.getSystemClassLoader().loadClass("Generator"+type); 
    final Generator generator = (Generator) (generatorClass.newInstance()); 
    return generator; 
} 

PS:我高度評價你遵循了Java的規則:如果generateXML是一個類,它應該寫成GenerateXML。

更多結束:通過命名你的類來照顧。 (1)對象generateXML支持擴展輸出,因爲它不是輸出。 (2)「GenerateXML」是一個動詞,即動作。因此,命名對象並不是一個正確的詞,而是一種方法。您可以按照示例「XMLGenerator」命名對象。

+0

感謝您的建議,但我對您的第二個提示有點困惑「」GenerateXML「是一個動詞,即一個動作,因此它不是一個正確的單詞,而是一個方法。 XMLGenerator「」你是指類名嗎? –

+0

是的,我願意。最好的是在我看來。 –

+0

是的,我願意。你應該命名你的類爲'XMLGenerator',通過'final Generator myGenerator = new XMLGenerator()'實例化它,並使用'myGenerator.generate()'這個實例。然而,在你的特定情況下,你將會有'Generator myGenerator =(Generator)(generatorClass.newInstance());' –

0

既然你不得不打電話new我不確定你可以繞過分支過程。有人必須知道什麼讓你回來。

如果是爲單身,你可以初始化一個HashMap的"xml"=>generateXML singleton

後第二不過,你可以修改您的字符串屬性爲型動物Type類MyTypeXML,MyTypeJSON,... 然後使用方法具有相同的名稱,但不同類型。

public Output generate(MyTypeXML xml) { // This will go for XML } 
public Output generate(MyTypeJSON json) { // This will go for JSON } 

但是對於工廠,我並不真的反對if ... else編碼。

2

你應該考慮用地圖替換你的if-else鏈。

而不是必須編寫代碼來檢查所有你想支持的字符串,你只需要一系列的線來從地圖中檢索元素。

當然,您將需要一些更多的配置代碼來將這些項目放入地圖中,但這應該是微不足道的。

Here它是關於這個話題(在PHP)好貼

1

您可以使用enum可根據枚舉通過傳遞給工廠,工廠的回報對象。唯一的問題是你不能將它作爲API導出。

enum Type 
{ 
    XML { 
     @Override 
     public Object getFactory() { 
      // TODO Auto-generated method stub 
      return null; 
     } 
    }; 

    public abstract Object getFactory(); 
} 

如果你不得不像API那樣暴露它,那麼你可以做下面的事情。

interface IType { 
    public abstract Object getTypeFactory(); 
} 

enum Type implements IType { 
    XML { 
     @Override 
     public Object getTypeFactory() { 
      // TODO Auto-generated method stub 
      return null; 
     } 
    }; 
} 

而變化的工廠方法implemetation到

public static Object getFactoryByType(String name) { 
    Type type = Type.valueOf(name); 
    return type.getTypeFactory(); 
} 
1

您可以使用反射。

Object generated = getClass().getMethod("generate" + type.toUpperCase()).invoke(this); 

public Object generateXML(); 
public Object generateJSON(); 
public Object generateCSV(); 
+0

感謝您的奇妙建議,理由是我必須學習反思!!(以前從未聽說過:)) –

+0

該appraoch的一個特點是,您可以添加方法而無需編寫額外的「佈線」代碼。 –

+0

這是一個很好的除了太陽的,以防萬一誰感興趣... [http://tutorials.jenkov.com/java-reflection/index.html](http://tutorials.jenkov.com/java -reflection/index.html) –