且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

创建一个递归迭代

更新时间:2023-11-23 23:00:28

您可以写一个迭代器会连接其子的迭代器,甚至懒洋洋地。呼叫下一个()歌曲的迭代器,然后将深入挖掘 MusicComponent 迭代器和最终实现下一个 MusicTime

You can write an iterator which "concatenates" the iterators of its children, even lazily. Calling next() on a Song's iterator would then drill down through the Section and MusicComponent iterators and finally deliver the next MusicTime.

番石榴使这个容易。让 MusicComponent 可迭代< MusicTime> 和实施迭代器()为:

Guava makes this easy. Make MusicComponent an Iterable<MusicTime> and implement iterator() as:

@Override
public Iterator<MusicTime> iterator() {
    return Iterables.concat(getChildren()).iterator();
}

由于所有的孩子都 MusicComponent 和由此实施可迭代&LT; MusicTime&GT; 自己,的迭代器将部分的串联迭代器,这本身就是 MusicTime 的串联>迭代器。

Since all children are MusicComponents and thus implement Iterable<MusicTime> themselves, Song's iterator will be a concatenation of Section iterators, which are themselves concatenations of MusicTime iterators.

这最后的迭代器是一种特殊情况。 A MusicTime 迭代器只能返回自己一次:

This last iterator is a special case. A MusicTime iterator should only return itself once:

@Override
public Iterator<MusicTime> iterator() {
    return Iterators.singletonIterator(this);
}

另外,的迭代器可以改为:

Alternatively, Section's iterator could be replaced with:

@Override
public Iterator<MusicTime> iterator() {
    return getChildren().iterator();
}

通过这一点,迭代变得那么容易,因为:

With this, iterating becomes as easy as:

for (MusicTime time : song) {
    player.play(time);
}

您现在可以做任何类型的操作(播放,计算总工期,...)无需重新执行递归。

You can now do any kind of operation (playing, counting the total duration,...) without re-implementing the recursion.

有您的问题的替代解决方案,虽然,但是这一切都归结到设计选择。例如,你可以有一个播放 MusicComponent 其中歌曲$ C $方法C>和通过调用将实施播放所有子女。这是一个简单的递归实现,但你必须为你要添加的 MusicComponent (如所有行动中发挥重复递归 getTotalDuration ,...)。

There are alternative solutions for your problem though, but it all comes down to design choices. For example, you could have a play method on MusicComponent which Song and Section would implement by calling play on all of their children. This is a straightforward recursive implementation, but you must repeat the recursion for all operations you intend to add on MusicComponent (such as play, getTotalDuration, ...).

如果您需要更多的灵活性,您可以使用 Visitor设计模式并让您的播放操作访客(如 PlayVisitor )。这样做的好处是,你可以决定控制从游客中的迭代顺序,但使得它很难增加新的 MusicComponent 的实施。

If you need more flexibility, you could use the Visitor design pattern and make your play operation a visitor (e.g. PlayVisitor). This has the advantage that you can decide to control the iteration order from within the visitor, but makes it harder to add new MusicComponent implementations.