Making Mock Data Circular
Was writing a test today where I was doing a Command Pattern that would allow me to contain a set of repeated invocations in a timebox. In other words: call me as many times as possible in x milliseconds. So for the test, I was using random #s, but that kept going to zero after a ton of invocations. Got out my Distribution class that allows me to say 'give me random #s with x% in range between y and z.' Once I do that, though, I have to know how many #s I am going to need, and I don't really.
First, I did the usual TDD thing: write it and let it fail. Sure enough, it fails on .next() after the iterator is exhausted. Did some searches on whether there is a reset method on some specialized iterator. But then, I decided it would just make more sense to make a simple CircularIterator, like so:
/**
* Provides the ability to give a fixed sample, and this class will provide an
* {@link Iterator} that will just repeatedly loop through the collection.
*
* @author Rob
*
* @param
* @Pattern Decorator
*
*/
public class CircularIterator implements Iterator {
/**
* Just using a real iterator here, after running through the set each time.
*/
private Iterator i;
/**
* The sample we want to cycle through.
*/
private Collection collection;
public CircularIterator(Collection collection) {
this.collection = collection;
this.i = collection.iterator();
}
/**
* Will always return true, since we are just looping.
*/
public boolean hasNext() {
return i.hasNext();
}
/**
* Gets the next element. If there are no more, the iterator {@link #i} is
* recreated.
*/
public T next() {
if (!i.hasNext())
i = collection.iterator();
return i.next();
}
/**
* Just proxies call so should work as usual.
*/
public void remove() {
i.remove();
}
}
Of course, this means that you are going to just get the same #s over and over again, but in a lot of cases (like mine), that doesn't really matter: scores, confidence levels, donations, whatever.
This is a good example of the Decorator pattern: it implements the interface, holds an instance of the type it's extending, and proxies on the methods it doesn't need to change. The nice part is that I can just create this, using the same declarations and then call next() for as long as I like.
From http://www.jroller.com/robwilliams
- Login or register to post comments
- 1666 reads
- Printer-friendly version
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)















Comments
fmarmar replied on Thu, 2009/06/25 - 2:36am
As you usually iterate over iterators in this way:
while (it.hasNext()) {it.next();
}
And the iterator index is moved when you call the next() method, your code should be:
public E next() {E element = i.next();
if (!i.hasNext()) {
i = collection.iterator();
}
return element;
}
Besides there is another problem with the remove method if you want to remove the last element of the iterator, you will get an IllegalStateException. The complete class right code should be:
Gerrit Cap replied on Thu, 2009/06/25 - 3:48am
None of the code above does work, if one would use an iterator that behaves circular, what is the point of calling hasNext() everytime ? Just imagine code that doesn't call hasNext() -- even if that would be bad practice -- and only calls next().
The hasNext() method should just return true by default unless the collection is empty that is. The next method on the other hand should check if the underlying iterator has any next elements, if not then re-instantiate it. Unless the collection is empty then it should throw a NoSuchElementException.
Although at first it seems to be a nice example of trying to apply the Decorator pattern the result by doing so will be very difficult to withstand any unit test on Iterator behaviour.
Gerrit
tiffanyjewelry replied on Fri, 2009/06/26 - 1:28am
unguiculus replied on Fri, 2009/06/26 - 1:28am
Rob Williams replied on Tue, 2009/07/07 - 7:35pm