Singleton
Singleton Concept
A singleton is a class that allows only one instance to be created. Typical examples of singletons include stateless objects and unique system components. However, singleton classes pose a challenge when it comes to testing, unless the type is defined as an interface and implemented separately.
How to Create a Singleton
Using a public static final field
The private constructor is called only once when the Elvis instance is initialized, ensuring that it's the only instance in the entire system. However, it's possible to call the private constructor using AccessibleObject.setAccessible(). This reflection-based manipulation can be prevented by throwing an exception when attempting to create a second object.
- Advantages
- Clearly indicates that the class is a singleton within the API.
- Concise.
Providing a static factory method as public static
Except for manipulation through reflection, this approach also guarantees that there's only one instance in the entire system. It simply changes the field to private and utilizes a static factory method for object retrieval.
- Advantages
- Allows for changing the singleton to non-singleton without modifying the API.
- For example, the static factory method can return a different instance for each thread.
- Can be changed to a generic singleton factory method if needed.
- Can use the method reference of the static factory as a supplier.
- For instance, you can use Supplier<Elvis> instead of Elvis::getInstance.
- Allows for changing the singleton to non-singleton without modifying the API.
If there's no need to utilize the above advantages, it's best to use the first approach.
Using an enum type
The most desirable approach is using an enum type. Compared to the previous two methods, it's secure against reflection attacks and offers cleaner code. Also, as explained later, the previous two approaches have a drawback of requiring additional code for serialization.
However, it's important to note that while a singleton created using this approach can inherit an interface, it cannot inherit a class.
Points to Consider When Serializing Singleton Classes
If you intend to serialize a singleton class created using the first or second method, you need to do more than just implement Serializable. You should declare all instance fields as transient and override the readResolve() method to provide a specific implementation.
Comments0