Item 21 - Use function objects to represent strategies
From Effective Java 2/e by Joshua Bloch
Java does not provide function pointers, but object references can be used to achieve a similar effect. Invoking a method on an object typically performs some operation on that object.
// Strategy interface
public interface Comparator<T> {
public int compare(T t1, T t2);
}
class StringLengthComparator implements Comparator<String> {
private StringLengthComparator() { }
public static final StringLengthComparator INSTANCE = new StringLengthComparator();
public int compare(String s1, String s2) {
return s1.length() - s2.length();
}
}
Concrete strategy classes are often declared using anonymous classes
Arrays.sort(stringArray, new Comparator<String>() {
public int compare(String s1, String s2) {
return s1.length() - s2.length();
}
});
If it is to be executed repeatedly, consider storing the function object in a private static final field and reusing it
// Exporting a concrete strategy
class Host {
private static class StrLenCmp implements Comparator<String>, Serializable {
public int compare(String s1, String s2) {
return s1.length() - s2.length();
}
}
// Returned comparator is serializable
public static final Comparator<String>
STRING_LENGTH_COMPARATOR = new StrLenCmp();
... // Bulk of class omitted
}
Conclusion
Primary use of function pointers is to implement the Strategy pattern.
- declare an interface to represent the strategy
a class that implements this interface for each concrete strategy
When a concrete strategy is used only once, it is typically declared and instantiated as an anonymous class
- When a concrete strategy is designed for repeated use, it is generally implemented as a private static member class and exported in a public static final field whose type is the strategy interface.