- 1) Singleton Creational Design Pattern
- 2) Eager Initialization
- 3) Static Block Initialization
- 4) Lazy Initialization
- 5) Thread Safe Singleton
- 6) Bill Pugh Singleton Implementation
- 7) Enum Singleton
- 8) When to use Singleton Creational Design Pattern?
- 9) Drawbacks of Singleton Creational Design Pattern
- 10) Singleton Creational Design Pattern Example
- 11) Source Code
Singleton Creational Design Pattern
Singleton Creational Design Pattern is a part of the classic Gang Of Four Creational Design Patterns. These deal with the creation/instantiation of Java Class objects in the best possible way in specific scenarios.
The basic way of creating an object i.e using the new operator and class constructor sometimes is not enough to deal with modern complexities in the System Design. To tackle such issues, we have below 5 Creational Patterns which could be used in specific scenarios:
- Singleton Pattern
- Factory Pattern
- Abstract Factory Pattern
- Builder Pattern
- Prototype Pattern
This tutorial is a part of the Creational Design Pattern Series. Take a look at other Creational Design Patterns:
- Singleton Creational Design Pattern Java Explained [6 Code Example]
- Factory Design Pattern Java Simplified [Simple Real World Example]
- Factory Method Design Pattern Java Simple Detailed Examples
- Abstract Factory Design Pattern Java Real World Example
- Builder Design Pattern Java Real World Example
- Prototype Design Pattern Java Real World Example
Singleton Creational Design Pattern
Singleton Creational Design Pattern is one of the most basic Gang of Four (GOF) design patterns. As the name suggests, this pattern will ensure that only a single instance of the class is created in the application.
Singleton design is very controversial among developers because of its design implementation concerns. Singleton design pattern is also used in other design patterns like Abstract Factory, Builder, Prototype, Facade, etc.
- To implement the Singleton pattern, we have different approaches but all of them have the following common concepts.
- Private constructor to restrict instantiation of the class from other classes. Also to ensure that this class doesn’t have any child classes.
- The private static variable of the same class that is the only instance of the class.
- Public static method that returns the instance of the class, this is the global access point for the outer world to get the instance of the singleton class.
We have different ways to implement the Singleton Creational Design Pattern :
- Eager Initialization
- Static block initialization
- Lazy Initialization
- Thread Safe Singleton
- Bill Pugh Singleton Implementation
- Enum Singleton
Eager Initialization
This is the easiest way to create a singleton class. The instance of Singleton Class is created at the time of class loading.
The Singleton class is created at the time of class loading, instead of when it is required by the application. This is a major drawback in case the Singleton class is heavy and might not be required in the application.
package com.adevguide.java.designpatterns.singleton; /** * @author pbhuite * */ public class EagerInitialization { // private construction so the class cannot be instantiated from outside also blocks inheritance private EagerInitialization() { System.out.println("A Singleton class is created using EagerInitialization."); } // private static final instance creation eagerly private static final EagerInitialization INSTANCE = new EagerInitialization(); // public class for outside world to get the instance public static EagerInitialization getInstance() { return INSTANCE; } }
If your singleton class is not using a lot of resources, this is the best approach to use. But in most of the scenarios, Singleton classes are created for resource hungry tasks such as File System, Database and Connections. We should avoid the instantiation until the client calls the getInstance method.
Also, this method doesn’t provide any options for exception handling.
Static Block Initialization
This implementation of the singleton is the same as eager initialization with an only difference as the addition of a static block. The instance of the class is created in a static block which provides exception handling options.
package com.adevguide.java.designpatterns.singleton; /** * @author PraBhu * */ public class StaticBlockInitialization { private static StaticBlockInitialization instance; static { try { // private static final instance creation instance = new StaticBlockInitialization(); } catch (Exception e) { System.out.println("Exception Occured" + e); } } // private construction so the class cannot be instantiated from outside also blocks inheritance private StaticBlockInitialization() { System.out.println("A Singleton class is created using StaticBlockInitialization."); } // public class for outside world to get the instance public static StaticBlockInitialization getInstance() { return instance; } }
Lazy Initialization
This implementation of the singleton will create an instance of the class only when it is required in the application.
package com.adevguide.java.designpatterns.singleton; /** * @author PraBhu * */ public class LazyInitialization { // private construction so the class cannot be instantiated from outside also blocks inheritance private LazyInitialization() { System.out.println("A Singleton class is created using LazyInitialization."); } // private static final instance creation lazy private static LazyInitialization instance; // public class for outside world to get the instance public static LazyInitialization getInstance() { if (null == instance) { instance = new LazyInitialization(); } return instance; } }
The above implementation works fine in the case of the single-threaded environment but when it comes to multithreaded systems, it can cause issues. If multiple threads are inside of the if loop at the same time, it will destroy the singleton pattern and both threads will get the different instances of the singleton class.
Thread Safe Singleton
This implementation of the singleton creational design pattern is somewhat similar to Lazy initialization. The public global access method is synchronized to make the implementation thread-safe.
package com.adevguide.java.designpatterns.singleton; /** * @author PraBhu * */ public class ThreadSafeSingleton { // private construction so the class cannot be instantiated from outside also blocks inheritance private ThreadSafeSingleton() { System.out.println("A Singleton class is created using ThreadSafeSingleton."); } // private static final instance creation private static ThreadSafeSingleton instance; // public class for outside world to get the instance public static synchronized ThreadSafeSingleton getInstance() { if (null == instance) { instance = new ThreadSafeSingleton(); } return instance; } }
Due to the use of synchronized keywords on method level, the performance of the implementation will be impacted. The synchronized method will be executed every time the instance is requested, while we only need to ensure thread safety in some initial threads when multiple instances could be created. To solve this, we can use the Double-Checked Locking Implementation.
package com.adevguide.java.designpatterns.singleton; /** * @author PraBhu * */ public class ThreadSafeDoubleLocking { // private construction so the class cannot be instantiated from outside also blocks inheritance private ThreadSafeDoubleLocking() { System.out.println("A Singleton class is created using ThreadSafeDoubleLocking."); } // private static final instance creation private static ThreadSafeDoubleLocking instance; // public class for outside world to get the instance public static ThreadSafeDoubleLocking getInstance() { if (null == instance) { synchronized (ThreadSafeDoubleLocking.class) { if(null==instance) instance = new ThreadSafeDoubleLocking(); } } return instance; } }
In this approach, the synchronized block is used inside if condition with an additional check to ensure that only one instance of the singleton class is created.
Note: With early versions of the JVM, synchronizing the whole method was generally advised against for performance reasons. But synchronized performance has improved a lot in new JVMs, so this is now a preferred solution.
Bill Pugh Singleton Implementation
This is the most optimized and preferred way of creating a Singleton class. Bill Pugh Singleton Implementation uses an inner static helper class to create an instance of the singleton class.
package com.adevguide.java.designpatterns.singleton; /** * @author PraBhu * */ public class BillPughSingleton { // private construction so the class cannot be instantiated from outside also blocks inheritance private BillPughSingleton() { System.out.println("A Singleton class is created using BillPughSingleton."); } // private static final instance creation private static class InnerStaticHelperClass { private static final BillPughSingleton INSTANCE = new BillPughSingleton(); } // public class for outside world to get the instance public static BillPughSingleton getInstance() { return InnerStaticHelperClass.INSTANCE; } }
The private inner static class contains the instance of the singleton class. When the Singleton class is loaded, SingletonHelper class is not loaded into memory.
Only when someone calls the getInstance method, this class gets loaded and creates the Singleton class instance. This is the most widely used approach for Singleton class as it doesn’t require synchronization.
Enum Singleton
Enum can be used to implement Singleton design patterns as Java ensures that any enum value is instantiated only once in an Application. Since Java Enum values are globally accessible, so is the singleton.
package com.adevguide.java.designpatterns.singleton; /** * @author PraBhu * */ public enum EnumSingleton { INSTANCE; public void getInstance() { //Perform some task here } }
The drawback is that the enum type is somewhat inflexible; for example, it does not allow lazy initialization and enum values are always immutable.
When to use Singleton Creational Design Pattern?
- For resources that are expensive to create like XML Marshall content, database connection objects, etc.
- Classes that contain resources that are accessed in shared mode.
- It’s good practice to keep all loggers as Singleton which increases performance.
- Classes which provide access to configuration settings for the application.
Drawbacks of Singleton Creational Design Pattern
- Singleton class by design hides the clear dependencies of the project. This might create a big issue when the size of the project is huge.
- Singleton design is hard to unit test as a single instance cannot be mocked.
- Whenever a singleton class is deserialized, it will create a new instance of the class.
- As the static keyword is used while implementing singleton, there will be one instance of the class per class loader. If there are multiple class-loaders running under a single JVM, multiple instances will be created inside JVM.
Singleton Creational Design Pattern Example
Singleton design pattern is used in core java classes such as java.lang.Runtime, java.awt.Desktop.
Source Code
As always, you can find all the source code used in this tutorial in our GitHub repository.