Summary
Pattern Name | Singleton Pattern |
Pattern Type | Creational Pattern |
Scope | Object |
Tagline | Ensure only one instance of a class |
Use cases | When we want to ensure that only one instance of a class is created in any case (Like for, Database connection, File handler, etc.) |
Related Patterns | Abstract Factory Builder Facade Flyweight Prototype |
Difficulty Level | Easy |
Implementations |
Definition
For some components/objects in the code, we just need one instance. So that we can store that instance globally and use that instance everywhere.
Like, a database connection or a logging handler, does not need a new instance each time we want to use it, the same instance can be used in all places. Singleton pattern comes into play, in that case.
Singleton pattern is used to ensure that only one instance of a class is created in any case, and whenever you want to get an instance of that class, then the same object instance is returned.
Singleton pattern also ensures easy global access to the singleton object. So we can query(ask for an instance) the class from anywhere(in the application) and the class will return back the same single instance.
WARNING
Singleton pattern may make it difficult to write easily testable code, because of the tight coupling of the class object and its methods.
Use Cases
When we want to handle a database connection or a file resource, we don’t need to create a new object each time. As we want the database connection or the file resource to point to the same connection/resource always.
So we can use Singleton in the following use cases:
- Database connection
- File resource handler
- Caching handler
- Logging resource handler
- Network socket connection handler
Implementation
Implementation of the Singleton pattern is simple and involves only one class (the Singleton class).
Use the following steps to implement the Singleton pattern.
Step #1: Prevent the creation of new instances manually
The constructor needs to be private so that a new instance of the class can not be created by using new operator.
Step #2: Make sure the instance is accessible from anywhere
Create a static method for getting the instance of that class. This static method will accept the parameters required to create a new instance of the class.
Step #3: Ensure the return of the same instance each time
- Use a class variable to store instances.
- If an instance already exists then return that from the static method.
- If no instance exists- then create a new instance, store the instance in the class variable, and return that instance from the static method.
Examples
Let’s take a look at a few examples where we need to use the Singleton pattern.
Example #1: Database Connection
Let’s take the example of creating a class for database connection.
Singleton Class
This is the class that has the Singleton implementation. Here are a few key points in the implementation:
class DbConnectionSingleton
var static dbInstance: DbConnectionSingleton
var url: String
var port: String
var username: String
var password: String
# Make sure to make it private, so that the constructor can be used directly
private constructor(
urlParam: String,
portParam: String,
usernameParam: String,
passwordParam: String
)
url = urlParam
port = portParam
username = usernameParam
password = passwordParam
end constructor
# Make this method static to access it directly
static method getInstance(
urlParam: String,
portParam: String,
usernameParam: String,
passwordParam: String
): DbConnectionSingleton
if (dbInstance == null)
dbInstance = new DbConnectionSingleton(urlParam, portParam, usernameParam, passwordParam)
end if
return dbInstance
end method
# Utility function for printing connection information
method printConnectionDetails()
output "URL:" + url
output "Port:" + port
output "User name:" + username
output "Password:" + password
end method
# Utility method for processing query (dummy)
method executeQuery(String query: String)
output "Executing query: " + query
end method
end class
Demo
While using the Singleton class, directly call the getInstance() method as it is static. No matter how many times the getInstance method is called, with different params, it will return the object that was created the first time.
Here we are calling the getInstance 2 times and the second time calls the object is not changed, and it returns the previous object instead.
# Create an instance of the connection
var dbConnection: DbConnectionSingleton = DbConnectionSingleton.getInstance("localhost", "5432", "postgres", "secret*pass")
output "First Connection Details:"
dbConnection.printConnectionDetails()
# Try creating another connection. This will return the previous existing connection
var secondDbConnection: DbConnectionSingleton = DbConnectionSingleton.getInstance("192.168.55.55", "1234", "postgres2", "secret*pass2")
output "Second Connection Details:"
secondDbConnection.printConnectionDetails()
Output
Here is the output generated from the code above.
First Connection Details:
URL: localhost
Port: 5432
User name: postgres
Password: secret*pass
Second Connection Details:
URL: localhost
Port: 5432
User name: postgres
Password: secret*pass
Code Implementations
Use the following links to check Singleton pattern implementation in specific programming languages.