Eric Burke recently gave some really great tips for legacy proofing your public APIs, including a really neat hack for protecting implementations from being publically instantiable, even if they are in a different package. I was so impressed by this completely obvious (in hindsight) hack that I thought I’d post it here.
Consider the case where you have a factory class or an abstract class which hides the actual implementation(s) behind a top-level static factory method. You (as the author of an implementation) might want to put your implementation in a different package, but this means you have to make the constuctor public (eek!). Eric’s hack involves creating a public Key class with a private (or default/protected) constructor so that only the factory can create an instance:-
public class MyFactory {
// public class, but private constructor
public final class Key {
private Key() {}
}
public static Widget createWidget() {
return new Gadget(new Key());
}
}
and then in the implementations, give them a constructor that takes in a Key!
public class Gadget implements Widget {
public Gadget(MyFactory.Key key) {
if (key == null) {
throw new IllegalArgumentException("Please use MyFactory");
}
}
}
Brilliant! Unfortunately, this breaks if you wish to use dependency injection and the factory class needs to know about the implementation. And, of course, your clients could always use sneaky reflection to create instances, but it should certainly make them think twice before tying themselves to a specific implementation.