Before you start
It's expected that the reader is already familiar with the term design pattern. Knows how to write a code in at least one Object Oriented Language(C#,Java etc). Understanding of Encapsulation. Constructor, Static Keyword.
What to expect
In this post I'll be talking about.
- What is a Singleton
- Why do we need it
- How to make one
- Refactoring
Singleton
What is a Singleton?
- Singleton is a design pattern that ensures that there is only one Instance of a class throughout the whole application.
Why Singleton?
- You might be wondering why do we need a class that we are only going to instantiate only once? Classes are made so that we can create objects of it. That is true but while writing clean codes you might want to follow some convention and follow some rules to write code. For example if you were to write a code for querying a database. You would want to make a manager class for handling connection. Lets call it ConnectionManager. If you think logically, You don't need to create more than one connection to database. So in this case you would like to have only one ConnectionManager Object. Now here you may ask, I can remember this. I'll not create 2 instances. I'll tell my team as well. That is certainly a solution. But will you remember that 5 years later? Or If your team grows can you tell everyone to keep track of singleton's manually? A design pattern is not a Rule. It's a Convention. If you follow a convention , it will enforce you and your team to write better code. It will ensure that you do not write bad codes by mistake. If you follow the singleton pattern, even you can't make another instance by mistake. So even if you forgot, The Singleton will remind you not to write bad code.
Lets make one
I'll be using C# to show how to make a singleton. But the logic behind it would be same for any other language.
First we Make a Class named ConnectionManager. And give it a constructor.
Here's the 1st problem. Our Constructor is public so you can always Create an object with
new ConnectionManager();
So we would like to prevent anyone from calling the constructor from outside. We need to make it private.
Now nobody can access the constructor from outside of the class. Now we are found with a new problem. So how do we get an instance of the object? We do want ONE instance. But the only way to create an instance we must need to call the constructor. WHICH by the way we just made private. So there is no way we can get an instance. For this we will take the help of static reference and keep one reference inside of the class.
Now we can get the instance of the class without accessing the constructor directly. Like this
ConnectionManager.Instance;
This is still far from what we would like to have. Because every time we GET the instance it just creates a new instance and gives us that. We don't want that. What we want is , If the instance does not have a reference of the object then we would want to get a new instance else we would like to get the existing instance. So What we would like to do is write a function that does exactly that. We need to add logic. And also lets make that Instance variable private so nobody can access it directly either.
Now if we call Connectionmanager.GetInstance();
We will get exactly what we wanted. Yeah that's all there is to it. You got yourself a singleton class. Whenever you call GetInstance it will give you the only existing object reference on the application.
I would leave this ?? operator for readers to do research. But I'll explain the code. Now you see, We always want the function to return An instance. so we are always returning the Instance variable. What we need to check is if the instance is null, We need to assign a new instance and return that. That's what I did in one line.
Now not only the code is more clean but also you can use the Instance like a variable instead of a function. Like this Connectionmanager.Instance;
But remember that this property is a C# feature. if you are writing a JAVA code you would need a function to get the instance.
Every public function inside of the singleton class can be accessed via that instance. Now you can't even create two Database connecting by mistake and save yourself from destroying your query system.
1:
public
class
ConnectionManager 2: { 3:
public
ConnectionManager() 4: { 5: //Some initialization 6: } 7: }
Here's the 1st problem. Our Constructor is public so you can always Create an object with
new ConnectionManager();
So we would like to prevent anyone from calling the constructor from outside. We need to make it private.
1:
public
class
ConnectionManager 2: { 3:
private
ConnectionManager() 4: { 5: //Some initialization 6: } 7: }
Now nobody can access the constructor from outside of the class. Now we are found with a new problem. So how do we get an instance of the object? We do want ONE instance. But the only way to create an instance we must need to call the constructor. WHICH by the way we just made private. So there is no way we can get an instance. For this we will take the help of static reference and keep one reference inside of the class.
1:
public class
ConnectionManager 2: { 3:
public static
ConnectionManager
Instance = new
ConnectionManager
(); 4:
private
ConnectionManager() 5: { 6: //Some initialization 7: } 8: }
Now we can get the instance of the class without accessing the constructor directly. Like this
ConnectionManager.Instance;
This is still far from what we would like to have. Because every time we GET the instance it just creates a new instance and gives us that. We don't want that. What we want is , If the instance does not have a reference of the object then we would want to get a new instance else we would like to get the existing instance. So What we would like to do is write a function that does exactly that. We need to add logic. And also lets make that Instance variable private so nobody can access it directly either.
1:
public class
ConnectionManager 2: { 3:
private static
ConnectionManager
Instance; 4:
private
ConnectionManager() 5: { 6: //Some initialization 7: } 8:
public static
ConnectionManager
GetInstance() 9: { 10:
if
(Instance==null) 11: { 12: Instance=new ConnectionManager(); 13: } 14:
return
Instance; 15: } 16: }
Now if we call Connectionmanager.GetInstance();
We will get exactly what we wanted. Yeah that's all there is to it. You got yourself a singleton class. Whenever you call GetInstance it will give you the only existing object reference on the application.
BUT WAIT
We can refactor the code. Lets start with refactoring the function. We are going to use ?? operator to change the function in one line.
1:
public static
ConnectionManager
GetInstance() 2: { 3:
return
Instance ?? (Instance =
new
ConnectionManager
()); 4: }
I would leave this ?? operator for readers to do research. But I'll explain the code. Now you see, We always want the function to return An instance. so we are always returning the Instance variable. What we need to check is if the instance is null, We need to assign a new instance and return that. That's what I did in one line.
It can be even better
In C# we have something called properties that act like a variable but can be written logic inside of it like a function.So we can remove the function entirely and make the class look something as simple as this.1:
public class
ConnectionManager 2: { 3:
private static
ConnectionManager
_singleton; 4:
public static
ConnectionManager
Instance => _singleton ?? (_singleton =
new
ConnectionManager
()); 5:
private
ConnectionManager() 6: { 7: //Some initialization 8: } 9: }
Now not only the code is more clean but also you can use the Instance like a variable instead of a function. Like this Connectionmanager.Instance;
But remember that this property is a C# feature. if you are writing a JAVA code you would need a function to get the instance.
Every public function inside of the singleton class can be accessed via that instance. Now you can't even create two Database connecting by mistake and save yourself from destroying your query system.
No comments:
Post a Comment