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.

  1. declare an interface to represent the strategy
  2. a class that implements this interface for each concrete strategy

  3. When a concrete strategy is used only once, it is typically declared and instantiated as an anonymous class

  4. 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.

Posted by The Finest Artist