多格式文件转换设计模式

5
过去,我曾尝试两次实现多格式转换器。一种是标记语言转换器,应该能够将GitHub、StackOverflow、MoinMoin、MediaWiki等转换。另一种是相册转换器,目前将ifolor转换为scribus,但应支持至少两种以上的相册格式和pdf。
问题总是相同的:不同的格式具有不同的特点。例如:MediaWiki和MoinMoin对宏的理解不同,而大多数其他标记语言不支持宏。或者ifolor有一些边框格式,在scribus中很难实现,也不好看。
我不喜欢为每种可能的组合实现直接转换器的想法(对于4种格式,这是12个转换器,有很多冗余)。我从“超集数据结构”开始,该结构包含所有格式的所有功能作为给定格式的导入和导出过滤器之间的链接,但我想知道是否有最佳实践方法来做这样的事情或类似设计模式的东西可能会有所帮助,例如一个导入和导出直接通信而没有“超级格式”的架构?

目前这两个项目因时间不足(和需求不高)而暂停了,但我愿意学习如何在下一次做得更好。相册为我的个人书籍完成了其工作,很可能很快就会继续。它的代码位于GitHub上。

2个回答

1
我会选择一个基本的“父类”,其中包含所有转换器共享的功能实现。然后是“接口”,用于每个转换器可以独有的功能,并且它们可用于了解哪个转换器支持哪个功能。最后是一个“工厂”实现,用于创建所需类型的转换器。
编辑以更好地解释自己:
你是正确的,基类是转换器。从快速查看您的代码并进行一些假设,您将拥有您自己指定的类(例如,ScribusWriter)作为输入。您可以为这些类创建一个通用的Writter。因此,我想象一些东西像:
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);
}

针对接口,从您关于某些格式支持宏,而其他格式不支持的描述中,我想到了一个指向支持宏的接口,这将帮助我们知道哪些支持和不支持,并在必要时“强制”实现。
我的建议是,您使用继承来基于特征/功能对类型进行分类,并避免常见功能的冗余。

你的“基础父类”是数据模型还是转换器?它更像是“转换器”,那么这个转换器的输入格式是什么?接下来的问题是:是什么在调用接口函数? - Daniel Alder
嗨@DanielAlder,我尝试通过编辑来详细阐述我的回答。 - martidis
嘿,我知道这个答案很旧了;但是,您能否通过编写几行代码来详细说明您在第一段中的意思? - zmerr
1
@James 说实话,我不记得这个答案了。看着它,我想我是指像 jdoodle.com/ia/gHc 这样的东西。我没有创建工厂部分。也没想过我的答案是否与帖子问题相关。希望这个例子能帮到你。祝好! - martidis
非常感谢您添加代码。它确实很有帮助。我是指您编写的转换器重构的想法。此外,我认为建造者模式可以成为此处工厂的良好替代品。例如:基于一个或多个格式中的冗余创建一系列建造者,并利用这些建造者进行增量转换。 - zmerr

0
如果您有多个不同格式的文件转换器,那么您可以使用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']

有趣的观点。也许更像是一个副回答。这可能对标记事物有所帮助(许多转换器,简单逻辑),但对于相册来说,更多的是少量具有复杂逻辑的转换器(每次转换都可能会丢失信息)。 - Daniel Alder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接