I am reading Effective Java. In a section that talks about using function objects as strategies, the below paragraph is present.
Because the strategy interface serves as a type for all of its concrete strategy instances, a concrete strategy class needn’t be made public to export a concrete strategy. Instead, a “host class” can export a public static field (or static factory method) whose type is the strategy interface, and the concrete strategy class can be a private nested class of the host
// 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
}
My question is , is there any particular advantage of using the above way? What is the problem with exporting the strategy by making concrete strategy public?
Yes, there is. This way you are returning the interface and not the concrete class, so if you change the concrete implementation of Comparator interface you don't have to modify client classes too (I think this is the most important reason of using interfaces).
For example:
//inside aClass
Comparator c = Host.STRING_LENGTH_COMPARATOR; //Programming against interfaces is different from:
StrLenCmp c = Host.STRING_LENGTH_COMPARATOR; //programming against concrete class
Suppose in the future you will change StrLenCmp with another implementation (let's call it NewStrLenCmp) than if you have programmed against interface Comparator you don't have to modify aClass.
Comparator c = Host.STRING_LENGTH_COMPARATOR; //still work because interface doesn't changed
NewStrLenCmp c = Host.STRING_LENGTH_COMPARATOR; // problem: you need to modify the client class in order to use the new concrete type: bad idea