Singleton - Harsh4999/Design-Patterns GitHub Wiki
Use
- A singleton class has only one instance, accessible globally through a single point via method or field
- It ensures that there is only one instance of a class
- Any state which you add in your singleton class it becomes part of global state of your whole application (Generally having a large global state is an indication of a bad design of application)
- We porovide a static method in the class which returns the only instance of the class
Implementation
-
Controll the instance creation
-
Class contructor are not allowed outside
-
Subclassing/interface must not be allowed
-
Class itself is a good place to track their instance
-
Two types
- Eager Sigleton (Early init)
- Create Singleton as soon as class is loaded
- Create private constructor
- Make a private var of same class and init it at the same time with the private contructor
- Make a public static method which returns localy initiate class
- No matter how many times the method is called to get instance same private class instance will be returned
- Lazy Singleton
- Dont create a Singleton unless a client asks for it
- In this we dont init the class with the application begining instead we wait till client req arises
- So to implement it we first of all make contructor private
- We then make a static volatile private var of same class but not init it
- We the make a static public method of getInstance
- We inside method first check if local var is not null which means its first time initiating the instance
- Then we write a synchronized block in order to ensure thread safety for a scenario like if 2 calls for get instance are made at same time then we ensure var is locked and not accesible to both at same time
- Then inside synchronized block we again check the instance value because if 2 threads came to synchronized block and only one was allowed first and it already created the instance then when second thread enters we dont want it to again reinit we just want to ensure a condition that INSTANCE is not null (this whole process is known as DOUBLE CHECK LOCKING)
- Also we used volatile keyword with local var because we also dont want threads to use instance from CPU local cache of that instance we want to block cache read/write valatile will force threads to read/write from main memory
- Volatile keyword was not there before v1.5 of java so we need to use different approach for solving cache issue in that versions of java
- Eager Sigleton (Early init)
-
Using eager init is most simple but if we want to consider on startup time to be less try to avoid it
-
Eg: Runtime class in java
-
Example code here
Pitfall
- They can deceive you about true dependencies since they are available globally accessible its easy to miss dep
- Difficult to test
- It uses static var which means One Copy Per Class Loader and not JVM so if we are using an Microservice or something and deploying application on same server it will create static instance per service (class loader) not per server JVM where its deployed
- Singleton carrying around lot of mutation in global state is good indication that we are actually misusing it