Let\'s say I want to design a class whose clients would need to call functions in a particular sequence, e.g.,
hasNext();
next();
or, as a
You might be interested in the Step Builder Pattern. It's not necessarily a good match for all the cases that you've presented, but the idea is that each operation returns something implementing an interface that lets you perform the next operation. Since you can only get the objects by performing the operations in the correct order, you'll be forced to perform them in the correct order.
While it would feel a bit forced in the iteration (next/hasNext) situation, you can imagine it for the
pattern. Somehow you get an instance of the CanWearSocks interface, which has only the following method.
CanWearShoes putOnSocks()
When you call putOnSocks(), you get your CanWearShoes instance, which has only the following method.
SockAndShoeWearer putOnShoes()
When you call putOnShoes() you now have something wearing socks and shoes, and you were forced to do it in the correct order.
What's particularly nice is that you can actually use the same object in both cases, but because the method signatures only return the interface type, code will only be able to use the interface methods (unless the code is sneaky, and casts the object to a different type).
Here's a rather contrived example that implements the iteration pattern, i.e., that makes sure that you use a NextChecker before a NextGetter.
public class StepBuilderIteration {
interface NextChecker {
NextGetter hasNext();
}
interface NextGetter {
Object next();
NextChecker more();
}
static class ArrayExample {
final static Integer[] ints = new Integer[] { 1, 2, 3, 4 };
public static NextChecker iterate() {
return iterate( 0 );
}
private static NextChecker iterate( final int i ) {
return new NextChecker() {
public NextGetter hasNext() {
if ( i < ints.length ) {
return new NextGetter() {
public Object next() {
return ints[i];
}
public NextChecker more() {
return iterate( i+1 );
}
};
}
else {
return null;
}
}
};
}
}
public static void main(String[] args) {
NextChecker nc = ArrayExample.iterate();
while (nc != null) {
NextGetter ng = nc.hasNext();
if (ng != null) {
System.out.println(ng.next());
nc = ng.more();
}
}
}
}
The output is:
1
2
3
4