更新时间: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 MusicComponent
s 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.