我有一个程序定期接收包含多行的文件,我逐行处理。为了处理这些行,我开发了一些文本规范化器,它们在整个生产线上进行转换。例如,一个规范化可能是删除停用词,语法纠正,删除网址等。
用于给定文件的规范化器必须动态决定,以便我可以更改它们的数量并改变它的顺序。对于某些文件,我只需删除,例如,停用词,但其他文件需要更多的规范化程序,在某些情况下,我必须应用两次。
我组织代码的第一个想法是应用Chain of Responsibility模式。在这种情况下,我会有这样的事情:
如图所示,按顺序使用了三个规范化器,然后再次使用第一个规范化器。这只是一个例子。在其他情况下,我可以有7个规范化器而不重复,而在其他情况下,第二个规范化器将在第三个之前执行。因此,主要的想法是拥有多个规范化器并在dinamically中定义一个可以重复的链。
我对这种方法的问题是链的所有成员总是被执行(没有拒绝条件)并且我有数千和数千行要处理所以我不想花费大量时间迭代链
所以,我的问题是,实现我需要的最好的方法是什么,让我有机会添加新的规范化器,而不必重写代码并保持链迭代的高速度?
如果您需要更多信息,请直接询问,我会编辑问题。
答案 0 :(得分:1)
“我对这种方法的问题在于链条的所有成员总是被执行(没有拒绝条件)并且我有成千上万行要处理,所以我不想花很多时间迭代链。“
大卫,
这有点矛盾。你说你想要执行所有规范化器,
例如1,2,3,1按此顺序从文件的每一行开始。但是你说你的
问题是你执行所有这些可能会减慢你的速度。是这个
标准化程序的顺序取决于您正在处理的当前行?
如果它不依赖,你需要在所有行上运行1,2,3,1,那么你就是
只需要这样做。我真的不明白你怎么能避免打电话给某些人
规范化器,但仍然在每一行上调用它们。
答案 1 :(得分:1)
我不知道以下内容是否符合您的建筑理念。
以XML格式的声明性 控制模型开始:
这可以推断出变化的综合效果。将控制消息(不再有标签)与实际操作(删除标签规范化器)分开可能是合适的。
可以使用POJO和注释使用 JAXB 读取XML。 非常简单。
控制胶可能记录所有,因此可以确定没有发生欠佳的事情。
答案 2 :(得分:1)
我想看看Lucene的分析器设计,它基本上是一个复合对象的抽象工厂(Analyzer
),并完成了与你所描述的相似的任务。
答案 3 :(得分:1)
当您为每一行执行所有规范化器时,设计模式是一个命令列表,因为没有检查每个规范化器的责任。
据我所知,规范化器列表对于每个文件是不变的,因此创建它不是问题。你还说你为每一行迭代所有这些,所以你唯一能调整性能的就是迭代本身。
我会使用这样的设计: 1)所有规范化器都实现了一个通用接口
interface Normalizer {
String normalize(String line);
}
你很可能已经有类似的东西了。
2)打开文件(或开始处理文件)时,确定需要哪些规范化器。除非你的文件很短并且你有很多文件,否则你的文件并不重要。您可以让工厂为某些条件返回正确的规范化列表。它可以使用类名的文本列表或创建硬编码的命令列表。还可以考虑Joop Eggen的答案。
class Factory {
List<Normalizer> buildNormalizers(DeterminingCriteria criteria) { ... }
}
如果您需要在不重新部署的情况下更改列表,则可以使用带有类名列表的文本文件。如果此时还需要添加新的规范化器,则无论如何都需要更改代码,因此构建规范化器列表的类也可以。
由于规范化器在这里需要无状态,因此可以在列表中重用双规范化器。实际上,您可以重复使用所有文件的所有规范化器,除非您的应用程序一次又一次地为每个文件启动。由于您的命令是无状态的,因此如果需要,它们还可以同时处理不同的文件。也许使用这样的设计:
class Factory {
private Map<Criteria, Normalizer> cachedNormalizers;
public Factory() {
// create all normalizers from a master map
// or hard coded here and add to map.
}
List<Normalizer> buildNormalizers(DeterminingCriteria criteria) {
// create an empty list and get normalizers from
// cached map depending on criterias you need.
}
}
3)然后在主代码中,您只需为每一行迭代这些代码。迭代列表应该非常快,就像那样(伪代码):
List<Normalizer> normalizers = factory.buildNormalizers(currentFileCriteria);
for (String line in lines) {
String currentLine = line;
for (Normalizer n in normalizers) {
currentLine = n.normalize(currentLine);
}
doSomethingWithFinished(currentLine);
}