2010-11-11 44 views
0

Java中可能創建一個靜態工廠方法/類,它使用接口作爲參數化類型並返回此給定接口的實現類?java參數化通用靜態工廠

雖然我的泛型的知識是有限的,這裏是我想做的事:

// define a base interface: 
public interface Tool { 
    // nothing here, just the interface. 
} 

// define a parser tool: 
public interface Parser extends Tool { 
    public ParseObject parse(InputStream is); 
} 

// define a converter tool: 
public interface Converter extends Tool { 
    public ConvertObject convert(InputStream is, OutputStream os); 
} 

// define a factory class 
public class ToolFactory { 
    public static <? extends Tool> getInstance(<? extends Tool> tool) { 
     // what I want this method to return is: 
     // - ParserImpl class, or 
     // - ConverterImpl class 
     // according to the specified interface. 
     if (tool instanceof Parser) { 
      return new ParserImpl(); 
     } 
     if (tool instanceof Converter) { 
      return new ConverterImpl(); 
     } 
    } 
} 

我想限制客戶端代碼只插入一個接口「類型」進入的getInstance()擴展方法從我指定的工具界面。這樣我就可以確定插入的工具類型是一個合法的工具。

客戶端代碼應該是這樣的:

public class App { 
    public void main(String[] args) { 

     Parser parser = null; 
     Converter converter = null; 

     // ask for a parser implementation (without knowing the implementing class) 
     parser = ToolFactory.getInstance(parser); 

     // ask for a converter implementation 
     converter = ToolFactory.getInstance(converter); 

     parser.parse(...); 
     converter.convert(... , ...); 
    } 
} 

工廠應在接口的類型轉換(粗疏,如果是空或不是),定義之前,從工廠問道。我知道這不會按照我寫這篇文章的方式工作,但我希望其中一位讀者知道我想完成什麼。

getInstance方法的返回類型與傳入參數相同,所以當傳遞一個Parser接口時,它也返回一個Parser p = new ParserImpl();返回p;

在此先感謝您的幫助。

回答

6

幾件事情:

  1. 你的工廠幾乎應該採取類實例化,而不是工具對象。讓某人創建一個Parser以傳入您的方法以獲得Parser是有點雞與雞蛋。
  2. 我不知道你是否被允許有通配符的通用參數;我認爲不會,因爲這將是荒謬和毫無意義的。當你參數化一個方法時,你需要給這個泛型參數一個名字,以便稍後可以引用它。

把這些在一起,你的工廠方法可能看上去就像這樣:

public static <T extends Tool> T getInstance(Class<T> toolClass) { 
    if (Parser.class.isAssignableFrom(toolClass) { 
     return new ParserImpl(); 
    } 
    else if (Converter.class.isAssignableFrom(toolClass) { 
     return new ConverterImpl(); 
    } 

    // You'll always need to have a catch-all case else the compiler will complain 
    throw new IllegalArgumentException("Unknown class: " + toolClass.getName()); 
} 

如果你想限制toolClass類型是一個接口,你不能在編譯時做到這一點,但您當然可以引入運行時檢查toolClass.isInterface()

順便說一下,這個靜態硬編碼切換不是很好不錯一般。在我看來,將類與構造關係放在Map中會更好,並動態查找構造過程。也許甚至可以將該值存儲爲Callable<? extends Tool>並添加受保護的方法,以允許其他類註冊映射。

這並不是說你目前的版本無法正常工作,只是它不能很好地擴展,現在我認爲它沒有太大的理由讓單獨的工廠而不是調用者調用toolClass.newInstance()自己。

+0

正是這樣做的方式。 – 2010-11-11 11:18:59

+0

感謝您的回答。不知何故,我沒有得到這個工作,因爲我心中...你能請詳細說明客戶代碼調用和Callable <?擴展工具>建議?我會跳過映射,因爲應用程序只有一些工具,並沒有超出這個範圍。 – user504342 2010-11-15 22:58:07