【问题标题】:Multi-format file conversion design pattern多格式文件转换设计模式
【发布时间】:2016-02-28 22:38:45
【问题描述】:

过去,我尝试过两次实现多格式转换器。一个是 Markup 转换器,应该能够转换 GitHub、StackOverflow、MoinMoin、MediaWiki 等。另一个是相册转换器,目前可以将 iflor 转换为 scribus,但应该支持至少两种以上的相册格式和 pdf。

问题总是一样的:不同的格式有不同的特性。例如:MediaWiki 和 MoinMoin 对宏的理解不同,而其他大多数标记语言不支持宏。或者 iflor 有一些边框格式很难在 scribus 中实现并且看起来不太好。

我不喜欢为每种可能的组合实现直接转换器的想法(对于 4 种格式,这是 12 个具有大量冗余的转换器)。我从一个“超集数据结构”开始,它包含所有格式的所有功能,作为给定格式的导入和导出过滤器之间的链接,但我想知道是否有最佳实践方法来做这样的事情或类似的事情有助于了解的设计模式,例如导入和导出直接通信而没有“超级格式”的架构?

嗯,这两个项目目前由于缺乏时间(和需求)而暂停,但我愿意学习下一次如何做得更好。相册为我的个人书完成了它的工作,并且可能很快会继续。它的代码在GitHub

【问题讨论】:

    标签: design-patterns file-conversion


    【解决方案1】:

    我会选择一个基础父类,它包含所有转换器共享的功能的通用实现。然后每个转换器可以唯一的功能接口,它们可用于了解哪个转换器支持什么功能。 最后是一个工厂实现来创建所需的转换器类型。

    在评论后编辑以更好地解释自己:

    你是对的,基类是一个转换器。通过快速查看您的代码并做出一些假设,您将拥有的输入是您自己指定的类(例如,ScribusWriter)。您可以为这些创建一个通用的 Writer。所以我会想象这样的事情:

    public abstract class BaseConverter {
    
        // common methods to avoid the redunduncies you mentioned
    
        public abstract <T extends BaseWritter> void convert(XmlBuilder xml, String input, T writer);
    }
    

    对于接口,我想到了您所写的有关某些格式支持宏而其他格式不支持的内容。因此,指向宏支持的接口将帮助我们知道哪些可以做,哪些不能做,并在必要时“强制”实现。

    我的建议是,您可以使用继承来根据特性/特性对类型进行分类,并避免常见功能的冗余。

    【讨论】:

    • 您的“基父类”是数据模型还是转换器?它读起来更像“转换器”,那么这个转换器的输入格式是什么?下一个问题:什么调用了接口函数?
    • 嗨@DanielAlder,我试图通过编辑详细说明我的回应
    • 嘿,我知道这个答案已经过时了;但是,请您介意用几行代码写下您在第一段中的意思来详细说明它吗?
    • @James tbh 我不记得这个答案了。阅读它我假设我的意思是这样的 jdoodle.com/ia/gHc 。我没有创建工厂部分。如果我的回答与帖子问题相关,也没有考虑清楚。希望示例对您有所帮助。欢呼
    • 非常感谢您添加代码。这确实很有帮助。我的意思是你写的重构转换器的想法。另外,我认为建造者模式可以很好地替代这里的工厂。就像基于一种或多种格式的冗余创建构建器的层次结构,然后使用这些构建器进行增量转换。
    【解决方案2】:

    如果您有多个不同格式的文件转换器,那么您可以使用 Dijkstra 算法找到两种文件格式之间的最短路径。此示例使用带有编程语言和编译器列表的 dijkstar 库:

    from dijkstar import Graph, find_path
    graph = Graph()
    
    for edge in [
        "C,JavaScript,Emscripten",
        "Java,JavaScript,JSweet",
        "JavaScript,Python,JS2Py",
        "Python,C++,Nuitka",
        "Python,JavaScript,Transcrypt",
        "JavaScript,PHP,js2php"
    ]:
        graph.add_edge(*edge.split(","))
    
    #print a conversion path
    print(find_path(graph, "JavaScript", "C++",cost_func = lambda a,b,c,d:1).edges)
    

    本例中,输入格式为"JavaScript",输出格式为"C++",转换路径为['JS2Py', 'Nuitka']

    【讨论】:

    • 有趣的地方。也许更多的是一个侧面答案。可能对标记有帮助(许多转换器,简单的逻辑),但对于相册来说,更多的是关于少数具有复杂逻辑的转换器(并且每次转换都有潜在的信息丢失)
    猜你喜欢
    • 2018-07-12
    • 2015-08-07
    • 2015-08-25
    • 2023-03-19
    • 1970-01-01
    • 2010-09-29
    • 2016-02-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多