6

考虑一个问题,我正在开发像 Collection 这样的树。

我的 Collection 的主要功能之一是逐个跟踪所有存储的项目,然后为每个项目调用给定函数,直到满足给定条件(惰性集合)。

因此该函数应具有以下签名:

void Trace(function func, criteria crit)
{
    item i = firstItem();
    while (i != endItem())
    {
        i = nextItem();
        func(i);
        if (crit(i))
            return;
    }
}

inC++函数指针可用于funccrit
C#,yield关键字正是这个问题的解决方案,我相信。

我怎样才能在 Java 中得到同样的东西?

4

4 回答 4

2

在 Java 中,您将传递对实现适用功能的类的对象的引用,或者使用 Commons Collections 代替:

例如:

Closure c = new Closure() {
    public void execute(Object obj) {
        ...
    }
};

Predicate p = new Predicate() {
    public boolean evaluate(Object obj) {
        ...
    }
}

Trace(c, p);
于 2012-12-28T01:34:28.673 回答
2

您在这里寻找的是策略设计模式。

此模式的目标是将算法的实现抽象为 Strategy 对象。在这里,您的算法是您要传入的func和函数。crit

所以,你会有一个接口,叫做TraceStrategy. 然后,您将此接口的实现传递到您的集合中。你的代码看起来像

void Trace(TraceStrategy traceStrategy)
{
    item i = firstItem();
    while (i != endItem())
    {
        i = nextItem();
        traceStrategy.func(i);
        if (traceStrategy.crit(i))
            return;
    }
}

interface TraceStrategy {
   public boolean crit(item i);

   public void func(item i);
}

你可能想让这个通用,这样你就不会被束缚在item……但你明白了。

于 2012-12-28T01:35:35.880 回答
1

创建一个声明方法的接口,并要求引用实现该接口的对象作为参数。调用者可以使用匿名内部类创建对象。

于 2012-12-28T01:34:00.907 回答
1

您可以通过结合几种技术使这个trace函数在 Java 中正常工作:

  • 而不是“函数指针”,您的参数func应该crit是实现特定接口的对象实例。然后你可以在对象的这个接口上调用一个函数i。实际上,这是一个具有两个不同访问者参数的访问者模式。
  • 您还需要一些方法来遍历树。您可以实现Iterator- 这为您提供了一种遍历整个结构的好方法。或者,您可以进行trace递归(它在树的左右分支上调用自身),然后您就不需要迭代器了。

迭代器版本看起来像这样:

public void trace(IFunction func, ICriteria crit) {
    for (T i: this) {
        func.call(i);
        if (crit.test(i)) return;
    }
}

这里T是集合的项类型,call和分别是和接口test中的函数定义。IFunctionICriteria

于 2012-12-28T01:38:52.477 回答