How to write a Singleton in proper manner?
The first thing which comes to my mind when creating a singleton is enum
. I generally use enum to implement singleton:
enum Singleton { INSTANCE;}
One benefit you get with using enum is with Serialization.
With singleton class, you would have to make sure that serialization and deserialization doesn't create a new instance by implementing the readResolve()
method, while this is not the case with enum.
Using class you should create the singleton like this:
public final class Singleton implements Serializable { // For lazy-laoding (if only you want) private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton() { if (SingletonHolder.INSTANCE != null) { // throw Some Exception } } public static Singleton getInstance() { return SingletonHolder.INSTANCE; } // To avoid deserialization create new instance @SuppressWarnings("unused") private Singleton readResolve() { return SingletonHolder.INSTANCE; }}
Latest Standard Solutions:
Core java with Managed Beans / CDI
@ApplicationScopedpublic class MySingleton { ... }
EJB Lite (JEE6)
@Singletonpublic class MySingleton { ... }
Prior Recommendation (from 'Effective Java 2'):
Use an enum, with a single bogus enumeration constant e.g. INSTANCE. Data fields and methods can be either static or non-static (instance) - the two behave equivalently, since there's only one instance
Advantages:
- Yep, it's a singleton. Impossible to create more than one instance by any mechanism (within any given class loader on any JVM).
- Singleton initialization is thread safe.
Disadvantages (compared with above Standard Solutions):
- The definition is a little obtuse - the 'enum' outer shell could misdirect inexperienced code maintainers. It's a small hack, not the original intention of enum.
- The implementation leaks through the abstraction. It violates theUniform Access Principle
- It doesn't work via injection - the client must know it is a singleton & code against the precise enum instance
- The client must use Singleton.INSTANCE.someMethod()
- The client can't (simply) code against an interface
- The client's impacted by design changes between singleton to/from multi-instance objects
- Extends an ancestor class (Enum), preventing inheritance from other classes
- Serialization & deserialization just transfer the enum constant name without state - good for technically ensuring there's only one instance, but a null operation with regards to data. In the (rare) event one wanted to share/synchronise singleton state across JVMs/class loaders, replication via serialization couldn't be used.
You can do
public enum Singleton { INSTANCE;}
and for a utility class which has no instances
public enum Utility { ; public static void method();}