pagetop
Javablog
by Java coders, for Java coders RSS

Private Implementations in Another Package

December 13th, 2007 by Sam

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.


This entry was posted by by Sam on Thursday, December 13th, 2007 at 11:51 pm, and is filed under API, Java, constructors, implementations, neat hack, visibility. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.


Leave a comment

Markdown is supported.

To include code snippets in your comment, use

<pre><code># lang java
... code here ...
</code></pre>

or use 4 spaces at the start of the line instead of using code and pre tags.

Comment feed: RSS