【问题标题】:Which design pattern to use to process different files in java?在java中使用哪种设计模式来处理不同的文件?
【发布时间】:2016-02-03 01:10:27
【问题描述】:

我有一个简单的任务是从不同结构的不同文件xml、rdf、txt中读取信息并将其放入一些POJO自定义对象(MyObject)中。所以我想知道使用哪种设计模式来使我的代码具有更好的设计。

我想到了这个问题,我认为我需要 Factory PatterIterator Pattern。 关于工厂传递文件:

ReaderFactory factory = new ReaderFactory("input.rdf");
//ReaderFactory factory = new ReaderFactory("input.xml");
Iterator<MyObject> iter = factory.getIterator();

因此工厂基于文件扩展名来选择要返回的迭代器的实现——读取 rdf、xml 或 txt。然后使用这个迭代器,我可以轻松地处理对象。添加添加新的文件扩展名在未来阅读。

【问题讨论】:

标签: java xml design-patterns rdf


【解决方案1】:

这是一个如何使用 FactoryStrategy 的示例。您创建一个AssetManager(工厂),并注册不同的AssetLoaders(策略)以及它们处理的文件扩展名。在运行时,您的 Factory 根据文件扩展名选择要使用的 Strategy

public interface AssetLoader
{
    public Object load(String name) throws Exception;
}

public class AssetManager
{
    private HashMap<String, AssetLoader> loaders = new HashMap<>();

    public void addLoader(AssetLoader loader, String extension)
    {
        loaders.put(extension, loader);
    }

    @SuppressWarnings("unchecked")
    public <T> T load(String name)
    {
        int i = name.lastIndexOf('.');
        if (i == -1)
            throw new RuntimeException("\"" + name + "\" has no extension, and so has no associated asset loader");

        String extension = name.substring(i+1);
        AssetLoader loader = loaders.get(extension);
        if (loader == null)
            throw new RuntimeException("No loader registered for \"." + extension + "\" files");
        try
        {
            return (T) loader.load(name);
        }
        catch(ClassCastException e)
        {
            throw new RuntimeException("\"" + name + "\" could not be loaded as the expected type");
        }
        catch(Exception e)
        {
            throw new RuntimeException("Failed to load " + name, e);
        }
    }
}

您所要做的就是为您想要支持的特定扩展创建实现 AssetLoader 接口的类。一旦你为它实现了加载器,你就可以像这样使用它:

AssetManager assets = new AssetManager();
assets.addLoader(new JsonLoader(), "json");
assets.addLoader(new XmlLoader(), "xml");

Iterator<MyObject> iter = assets.load("input.xml");

您可以更进一步,将其设为单例,这样您就不必在每次要加载另一个文件时重新注册不同的加载器。

这种方法为以后支持新的文件类型提供了更多的灵活性。它确实增加了代码的复杂性,但如果您计划添加对多种文件类型的支持,那么它可能是值得的。

【讨论】:

    【解决方案2】:

    将您的解决方案视为一种设计模式比将设计模式视为您的解决方案要好。

    如果您已经考虑过这一点,那么我认为,Strategy Pattern 可能更适合您的情况。

    我假设无论文件格式如何,您读取输入文件的方式都将保持不变。但是您可能希望根据文件的内容构建 POJO。

    例如:

    interface FileProcessor {
     public POJO process(BufferedReader br);
    }
    

    可以跨类实现相同的接口。

    class RDFFileProcessor implements FileProcessor {
     public POJO process(BufferedReader br) {
      // do your processing logic for rdf file content.
      return POJO;
     }
    }
    

    【讨论】:

    • “将您的解决方案视为一种设计模式比将设计模式视为您的解决方案要好。”听起来真的很深刻!但是我知道你的意思。你能详细说明一下吗?
    【解决方案3】:

    我认为您应该停止尝试重新发明轮子。至少使用已经解决了这个问题的RDF4jJena 来读取RDF。我推荐 RDF4j 而不是 Jena,它更容易使用,但两者都可以正常工作。

    然后你可以使用 Pinto 之类的东西(免责声明,我是作者)将解析后的文件映射到 POJO,类似于 Jackson & JSON。

    RDF4j 和 Jena 在他们的网站上都有关于如何使用他们的解析器的很好的文档。我知道 RDF4j 会根据文件扩展名选择正确的解析器,这就是你所说的。

    为自己节省一些时间和精力,使用一个库来为你做这件事,并真正专注于你的应用程序。

    【讨论】:

    • 此代码用于我的家庭作业,我必须使用两种模式。我不想使用自定义库。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-23
    • 1970-01-01
    • 1970-01-01
    • 2018-06-03
    • 1970-01-01
    • 2010-10-06
    相关资源
    最近更新 更多