Singleton design pattern for beginners.
Background -
When you want to restrict your class from creating more than
one object at a time or when you have a requirement where you want to maintain
a single session on web application, who will record all your activity, or a
logger application (one logger for all sub modules), please use singleton
design pattern.
For example –
a.
When you do online shopping. Your global login
get create and it remembers all item picked by you during your active session.
b.
We create single log file for any S/W
application per day. It will help us to debug issues. It will be very messy if
we create thousands of log file on each usages of different
module/functionality. Debugging will become hell.
We have plenty of examples where we use singleton design
patter in our S/W. This is very easy, popular and useful design patter.
We can also restrict the number of object to be initialized.
For example, I would like to have only 7 objects to get created, any attempted
to create more than 7 should get warning message.
We can implement it through singleton design pattern by
having a count increment variable in it.
Singleton design pattern -
Very important thing are,
1.
We will declare constructor as private, So that
other should not be able to create the object.
2.
Our code will have a static method, which will
return the pointer/reference of existing object.
3.
Have a counter variable if there is a requirement
of creating certain number of objects (for ex - 7).
UML representation –
Example –
/************************************************************************************** /* * Pro4 * Singleton design pattern. * (c) 2015 Kunjesh Singh Baghel, All Rights Reserved. * https://sites.google.com/site/kunjeshsinghbaghel/ * * ***************************************************************************************/ //************************************************************************************* // Header files #include<iostream> using namespace std; //************************************************************************************* // class Singleton { private: //zero argument copy constructor. Singleton(){} //Copy constructor. Singleton(Singleton &){} // overloaded assignment operator. const Singleton& operator = (Singleton &){} // single pointer which will get refereed in all the places. static Singleton *mp_singleton; public: static Singleton* GetInstance(); }; //************************************************************************************* // Static member variable definition Singleton* Singleton::mp_singleton = NULL; //************************************************************************************* // member function definition -- GetInstance() // very first implementation which come and which is not // a good implementation will looks like below - /* Singleton* Singleton::GetInstance() { //Lock lock; if(mp_singleton == NULL) mp_singleton = new Singleton;
// release lock
return mp_singleton;
}
*/
// what is the problem with above mentioned implementation ?
// - First if threads are coming sequentially then first time it will lock and create
// the pointer, but once it create singleton pointer for all other call it has to
// go to else part and return the created pointer. unnecessary we will bear the
// cost of lock and unlock else block though we have already created pointer.
//*************************************************************************************
// member function definition -- GetInstance()
// Second most answered implementation is
/*
Singleton* Singleton::GetInstance()
{
if(mp_singleton == NULL){ //first time check
//Lock lock;
mp_singleton = new Singleton;
// release lock
}
return mp_singleton;
}
*/
// what is the problem with above mentioned implementation ?
// - what if 2 threads come at same time in if condition and both went inside and
// locked by synchronization variable? then once first thread create pointer
// second thread will also create pointer as it is already inside of if block.
// Then we will end up with two pointer though it supposed to have only one
// as per singleton principle.
//*************************************************************************************
// member function definition -- GetInstance()
// third most answered implementation is - Double-Checked Locking Pattern ( DCPL )
Singleton* Singleton::GetInstance()
{
if(mp_singleton == NULL){ //first time check
//Lock lock;
if(mp_singleton == NULL) // second time check
mp_singleton = new Singleton;
// release lock
}
return mp_singleton;
}
//*************************************************************************************
//entry point
int main(int argc, char ** argv)
{
Singleton *ptr1 = Singleton::GetInstance();
cout<<"Address of pointer one is - "<< &ptr1 <<endl;
cout<<"Address of pointer Singleton pointer from pointer one is - "<< &(*ptr1) <<endl;
Singleton *ptr2 = Singleton::GetInstance();
cout<<"Address of pointer Two is - "<< &ptr2 <<endl;
cout<<"Address of pointer Singleton pointer from pointer two is - "<< &(*ptr2) <<endl;
}
/*
---------------------------------OutPut
$ ./a.exe
Address of pointer one is - 0x22caf8
Address of pointer Singleton pointer from pointer one is - 0x6000104c0
Address of pointer Two is - 0x22caf0
Address of pointer Singleton pointer from pointer two is - 0x6000104c0
*/
Thanks for reading it. To read more on design patterns and basic design principles please see my web page. You can also join me on FB or on G++. Please drop comments for any question related to this blog.
Comments
Post a Comment