2014-02-06 109 views
0

我有以下的抽象类爪哇 - 动态实例化抽象类

public abstract class Document { 
    private File file; 
    public Document(File f) { 
    this.file = f; 
    } 

    ... 

    public abstract String parse(); 
} 

目前,我有一个扩展DocumentJsonDocumentXmlDocument两班。

在另一个类DocumentContent中,我有函数遍历json和xml文件的一些集合,并调用parse()函数来提取某些内容。

如何根据检测到的文件扩展名动态实例化Document对象,而无需使用条件语句?将来会添加其他文件扩展名,我希望避免每次创建新的Document类类型时都需要更新DocumentContent。

+1

工厂模式。 –

+0

只是一个想法,但你可以得到的文件扩展名(json或xml),大写的第一个字母和concatentate与“文档”创建类名称,然后newInstance()该类 - 这将涵盖你的JsonDocument和XmlDocument 。但是这种方法迫使你命名类<文件扩展名>文档。 – mikemil

回答

2

您可以选择使用反射或没有,没有反射你需要设计一个建设者,是这样的:

abstract class DocumentBuilder { 
    public abstract Document build(File file); 
} 

HashMap<String, Builder> builders = new HashMap<String, Builder>(); 
builders.put("xml", new Builder(){ 
    public build(File file) { return new XMLDocument(file); } 
}); 

Builder correctBuilder = builders.get("xml"); 
if (correctBuilder != null) 
    return correctBuilder.build() 

与反思这将是类似的,但你会使用由反射本身给出的newInstance设施:

HashMap<String, Class<? extends Document>> builders = new HashMap<String, Class<? extends Document>>(); 
builders.put("xml", XMLDocument.class); 

try { 
    Document document = builders.get("xml").newInstance(); 
} 
catch (...) 
+0

“*我想避免每次创建新Document类型时更新DocumentContent。*”您的解决方案如何解决这个问题? – Vulcan

+0

@Vulcan通过将地图/构建器放在“DocumentContent”之外?或者我们正在讨论神奇地将扩展关联到构建器,并根据某种黑魔法生成新实例?像Java那样想象应该用XMLDocument类来解析“xml”扩展。除非你打算按名称找到课程并加载它(通过假设它们将始终对应),但我不打算提出一个如此糟糕的设计选择。 – Jack

+0

[我喜欢黑魔法](http://stackoverflow.com/a/21594927/1247781),但这确实是一个糟糕的设计选择。你有我的+1。 – Vulcan

1

很简单的事情做的是有一个DocumentFactory像这样:

public class DocumentFactory { 
    public static Document createFrom(File f) { 
    //Produce the right kind of Document based on the File instance 
    } 
} 

使用此创建您的所有Document秒。

然后因为每个文档都知道如何解析本身,你可以使用多态,只要前进,你总是与Document抽象引用每个:

for (Document document : documents) { 
    document.parse(); 
} 
0

我几年前有一些类似的要求,并通过使用策略模式和简单工厂模式(而不是工厂方法模式)

public class DocumentContent{ 
    Document document; 
    //other code 
} 

的组合所以,现在你DocumentContent由文档的解决了这个问题。这使您可以灵活地动态调用Document类的方法。我会建议你最好有文档作为在子类中实现的接口。你可以实例化如下:

document = new JsonDocument(); 
//OR 
document = new XmlDocument(); 

并基于文件扩展名,你可以实例化任何一个类。您可以轻松添加/删除新文档,而无需进行太多更改。