views:

107

answers:

5

Item 3 of Josh Block's Effective Java (Enforce the Singleton Property With a Private Constructor or an Enumerator) mentions that "While this approach has yet to be widely adopted, a single-element enum type is the best way to implement a singleton."

Example:

   public enum Elvis {
       INSTANCE;
       private final String[] favoriteSongs =
           { "Hound Dog", "Heartbreak Hotel" };
       public void printFavorites() {
           System.out.println(Arrays.toString(favoriteSongs));
       }
   }

Continued: "This approach is functionally equivalent to the public field approach, except that it is more concise, provides the serialization machinery for free, and provides an ironclad guarantee against multiple instantiation, even in the face of sophisticated serialization or reflection attacks."

The biggest negative I see is: aren't enums not supposed to have mutable state? It seems common to use a Singleton with state.

So has this pattern actually become more common since the publication date (2nd Edition published 2008)?

+2  A: 

Enums can have mutable state. It's usually not a good idea because the nature of an enum is to have exactly X versions of a Type Y where X is larger than 1, so juggling around state (other than using fields/properties) becomes a bit of a nightmare as each method needs to take into account all possible state of all X enum constants.

But if you are going to define an enum with only one constant anyway; you can simply treat that single constant as an ordinary object and make all the assumptions that come with it. IOW: the problem of having X versions of state goes away because X is now 1.

+6  A: 

While enums aren't generally given mutable state, this fact is based on assumptions of how an enum is going to be used. While these assumptions usually hold, they don't always, and one such case where they do no is in the creation of a Singleton.

While it's not the most common use of enums, it's perfectly legitimate to have an enum with a mutable state, though you may want to indicate this fact in your code so any other programmer who might be looking at it don't get confused.

As for a popularity of this design pattern, I've seen it fairly often, but not so much that I'd say it has become "common."

tlayton
+4  A: 

(This answer presumes that an "enforced" singleton is really what you want, as opposed to a de facto singleton managed by your DI framework (e.g. Guice's @Singleton), which is probably more often the right idea.)

To decompose your question into two: Is it really widely adopted? No, not as widely as it should be. Is it a good idea? Yes!

A Java enum is a class that can have only a fixed set of N instances, which are hardcoded in the source.

A singleton is a class that can have only a fixed set of N instances, which are hardcoded in the source. And N == 1.

It's as simple as that!

Kevin Bourrillion
+1  A: 

No enums are not supposed to have mutable state. Statics should not usually be mutable. Singletons are just ways to obfuscate mutable statics. (Stateless objects that implement an interface are another matter.)

Tom Hawtin - tackline
A: 

It's not a good idea.

It forces your class to inherit from a concrete class Enum. That pollutes your type hierarchy.

The type of the INSTANCE must be exactly Elvis; it cannot be some subtype of Elvis.

More generally you have no freedom to choose how the instance is instantiated.

And syntax-wise, is this really too much typing?

public class Elvis {
    static public Elvis INSTANCE = new Elvis();
irreputable
If you think it's remotely equivalent to what you typed here, I highly recommend reading the EJ article. And no one is forcing you to expose the Elvis as an Elvis. You can expose it (via a method) as whatever supertype you want, and this is a good general practice anyway as it leaves you the flexibility to use lazy initialization when you choose. That dispatches one of your concerns, and what does "pollutes your type hierarchy" even mean?
Kevin Bourrillion