0

假设您有 a List<Elements>in memory 和 a List<Files>,每个都是一个序列化的表示List<Elements>

目标是对每个元素执行相同的算法。

假设工作是计算元素

int i = 0;
for (Element e : list) {
       ++i;
}

for (File f : directory()) {
    for (Element e : listWeSomehowGetFromTheFile) {
           ++i;
    }
}

这可以以某种方式进一步抽象吗?本质上,算法是相同的(++i)。有没有办法清理这个?

我当然可以拥有它自己的类Counter(List<Element>),它具有count ()在列表中运行算法的方法。这样我们可以:

 i+=Counter.count(list);
 for (File f : directory()) {
   i+=Counter.count(listWeSomehowGetFromTheFile);
 }

但即使这样似乎也可以改进。

出于本示例的目的,假设所有操作(其中一堆)都将在内存中的列表和来自相同目录中相同文件的列表上执行。唯一会改变的是算法。

哪种模式最适合处理这样的事情?

4

2 回答 2

1

当您想对集合中的每个项目执行某些操作时,访问者模式非常流行。

访问者模式也很好,因为它允许您扩展您可以执行的计算,而无需重写访问者操作的类。

如果您不需要完全遵循正式模式,

1)定义一个接口,就像一个接受一个元素并进行操作Operation的方法一样。 2)您的计算是. 3)循环你的元素,将元素传递给你的操作实现。calculate
Operation

如果计算的结果是累积的(取决于先前对其他元素的计算调用),您可以修改calculate以获取包含计算状态的对象,然后在calculate针对元素触发时更新状态。您不断将相同的状态对象传递给每个计算调用。

作为大纲(这不会编译):

public Interface Operation {
   // don't necessarily need state
   public void calculate (Element e, State state);
}

CountOp extends Operation {
   count = 0;

   public void calculate(Element e, State state){
      // not using element or state because this is so simple....
      count++;
   }
}

Operation op = new CountOp();
State state = new SomeStateImpl();
for (File f : directory()) {
    for (Element e : listWeSomehowGetFromTheFile) {
          op.calculate(e, state);
    }
}
于 2012-07-26T20:47:30.157 回答
0

我可能会误解,但我处理这个问题的方法是根据(惰性)序列编写函数 - 将文件中的列表和数据都制作成惰性值序列很容易。

在更实际的情况下,java 中的惰性流通常实现为可迭代对象(或迭代器,如果您不需要重新启动),并且 guava 库有许多实用程序可以处理这些。

this assumes that elements are of the same type. the visitor pattern is more suited for when the data structure you are processing has different types (the visitor is where you do type based dispatch; that's not necessary for a single type, so the visitor pattern for a single type is equivalent to generating a stream of data - in that case it's simpler to use existing iterators).

于 2012-07-26T22:57:10.460 回答