Saturday, 22 November 2008

tem 3: Enforce the singleton property with a private constructor or an enum type

Ah, the Singleton pattern. Leaving aside any reservations we may have over the wisdom of using singletons - and the item does flag up the complication to testing that the pattern introduces - the various common methods of implementing singleton classes are discussed, concluding with a recommendation to use a Java 1.5 feature; an enum type.

Before release 1.5, the two options available both involved restricting the instantiatability of the singleton class through declaration of a private constructor, then providing access to the sole instance by slightly different approaches.

The first approach is to provide a public static final INSTANCE field. This is a very simple solution, but is inflexible: the INSTANCE field is in the public interface of the class, setting it's singleton status in stone. This is presented in a positive light, as it makes it clear that the class is a singleton. I remain unconvinced: this exposure of implementation detail in the interface is one of the flaws of the pattern.

This is alleviated by the second approach: make the INSTANCE field private, and add a public static factory method. Item 1 already mentioned the use of static factory methods in managing instance-controlled lasses: this is an example. Because the instance is now returned from a method, the creation policy can be changed without affecting the public interface.

Both these solutions have an issue with serializability. Deserialization usually instantiates a new object, which rather breaks the singleton model. For a singleton to be serializable, it needs to provide a readResolve method, which can return the sole instance instead of the newly instantiated one. This technique is the subject of its own item (way down at #77), but in summary it is a bit messy, and just one more thing you need to worry about. Is there a simpler solution?

As of release 1.5, the answer is yes. One of the new features of this release was enum types. An enum type is a type whose fields consist of a fixed set of constants. But enum types are also fully-fledged classes, which are instance-controlled.

Item 30 investigates the features of enum types in depth. For now, the key point is their conceptual similarity to singletons, meaning that support for singletons is now more or less built in to the language. The third, and preferred, implementation is as follows:
public enum Elvis {
INSTANCE;

public void leaveTheBuilding() { ... }
}
This is an admirably simple solution. I do feel uncomfortable however that Elvis is once again committed to being a singleton for life. And what would Priscilla have to say about that?

Ewan Milne

No comments: