By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,190 Members | 839 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,190 IT Pros & Developers. It's quick & easy.

singleton pattern - design question

P: 9
Hello,
I'm building an application, in which I have a ConfigManager class to hold all the important info about the application.
I need only one instance of ConfigManager class to be available throughout the application, from anywhere inside the application. From what I have read, the singleton pattern seems to match my problem
However, I built the ConfigManager with a constructor with parameters.

Until now, I've tried using global variables. One instance of ConfigManager class declared as global and used throughout th app. It works, but I am not very confortable with this. That's why I need a second opinion.

Thanks,

Adina
Mar 10 '07 #1
Share this Question
Share on Google+
14 Replies


sicarie
Expert Mod 2.5K+
P: 4,677
Hello,
I'm building an application, in which I have a ConfigManager class to hold all the important info about the application.
I need only one instance of ConfigManager class to be available throughout the application, from anywhere inside the application. From what I have read, the singleton pattern seems to match my problem
However, I built the ConfigManager with a constructor with parameters.

Until now, I've tried using global variables. One instance of ConfigManager class declared as global and used throughout th app. It works, but I am not very confortable with this. That's why I need a second opinion.

Thanks,

Adina
Have you tried to create the singleton, and then (creating and) using setVariable() methods?
Mar 11 '07 #2

P: 1
Hello,
I'm building an application, in which I have a ConfigManager class to hold all the important info about the application.
I need only one instance of ConfigManager class to be available throughout the application, from anywhere inside the application. From what I have read, the singleton pattern seems to match my problem
However, I built the ConfigManager with a constructor with parameters.

Until now, I've tried using global variables. One instance of ConfigManager class declared as global and used throughout th app. It works, but I am not very confortable with this. That's why I need a second opinion.

Thanks,

Adina
As far as I know you can create singleton's with parameterized constructors but the problem is who will assign the parameters? If you can make that decision then it will be possible. Try lookin in http://ehsanbraindump.blogspot.com it has some good content on singletons.
May 28 '07 #3

P: 93
Hello,
I'm building an application, in which I have a ConfigManager class to hold all the important info about the application.
I need only one instance of ConfigManager class to be available throughout the application, from anywhere inside the application. From what I have read, the singleton pattern seems to match my problem
However, I built the ConfigManager with a constructor with parameters.

Until now, I've tried using global variables. One instance of ConfigManager class declared as global and used throughout th app. It works, but I am not very confortable with this. That's why I need a second opinion.

Thanks,

Adina
I think you can make design of your class this way

code removed per posting guidelines Hope this solves your problem. Cheer up !!!
May 29 '07 #4

AdrianH
Expert 100+
P: 1,251
A singleton pattern is simple to do if you do it right. It can be disastrous if done wrong.

Expand|Select|Wrap|Line Numbers
  1. class A {
  2.   A(/* parameters */) {
  3.     /* init code */
  4.   }
  5.  
  6.   ~A() {
  7.     /* destruction code */
  8.   }
  9.  
  10.   A(A const&);
  11.  
  12. public:
  13.    A& instance() {
  14.     static A singleton(/* parameters */);
  15.     // or if no parameters use
  16.     static A singleton;
  17.     return singleton;
  18.   }
  19. };
  20.  
NOTE:
  • Iíve made the constructor and destructor private. This keeps others from trying to create a new instance.
  • Iíve also made the copy constructor private and without a body. This will keep you from inadvertently copying the object.
  • Iíve also made a singleton object as a static member in a class member function. This is very important as if you do not, it is possible that the initialisation fiasco will come in to play. See these articles for more information.

    Since it is declared as part of the class, it will be destroyed when the application terminates as it has rights to access the destructor

If you perform any operations on the instance, it is up to you to make it thread safe if you are working in a multi-threaded environment.


Adrian
May 29 '07 #5

AdrianH
Expert 100+
P: 1,251
I think you can make design of your class this way

code removed per posting guidelines Hope this solves your problem. Cheer up !!!
Hmm, I'm not sure who deleted your code. I don't think it violated the guidelines in this case.

Perhaps an example would have been better.


Adrian
May 29 '07 #6

P: 93
Hmm, I'm not sure who deleted your code. I don't think it violated the guidelines in this case.

Perhaps an example would have been better.


Adrian
Who deleted the example code with comments. Perhapps you would not
have If you know the pain of Design Issues. Amount of time I spent and
posting done by the OP becomes mere waste, which should not be the motto.

Thanks,
Girish Kanakagiri
May 30 '07 #7

P: 93
Hello,
I'm building an application, in which I have a ConfigManager class to hold all the important info about the application.
I need only one instance of ConfigManager class to be available throughout the application, from anywhere inside the application. From what I have read, the singleton pattern seems to match my problem
However, I built the ConfigManager with a constructor with parameters.

Until now, I've tried using global variables. One instance of ConfigManager class declared as global and used throughout th app. It works, but I am not very confortable with this. That's why I need a second opinion.

Thanks,

Adina
This time I hope nobody deletes it. Find the example piece of code
created by me and get the complete benefit out of it.
Let me know if you still have problem.

Class Designing -----

Expand|Select|Wrap|Line Numbers
  1. class ConfigManager
  2. {
  3.  private:
  4.       ConfigManager(type parameter);
  5.      // some more functions and data members
  6.  
  7.  public:
  8.      static ConfigManager* inst_;
  9.      static ConfigManager* crt_inst(type parameter);
  10.     // some more data members and functions
  11. };
  12.  
  13. ConfigManager::ConfigManager(type parameter)
  14. {
  15.   // Fill up the body
  16. }
  17.  
  18. ConfigManager* ConfigManager::inst_ = 0;
  19.  
  20. ConfigManager* crt_inst(type parameter)
  21. {
  22.   if(inst_ == 0)
  23.   {
  24.     inst_ = new ConfigManager(parameter); // parameter 
  25.  
  26. is same which is passed to crt_inst
  27.   }
  28.   return inst_;
  29. }
Implementation part ------

Expand|Select|Wrap|Line Numbers
  1. ConfigManager *cptr;
  2. cptr = ConfigManager :: crt_inst(parameter); 
  3.  
  4. /* pass the parameter which is required for the constructor, but 
  5.  
  6. remember only first time passed parameter will be 
  7.  
  8. retained since instance of the class will be only one */
  9.  
  10. // Now cptr points to instance of ConfigManager class, make use of it
  11.  
Regards,
Girish Kanakagiri
May 30 '07 #8

AdrianH
Expert 100+
P: 1,251
Girish Kanakagiri,

The Moderator who snipped out your code appologises. I talked to him/her. The reason was because you were posting a lot of code that was against the Posting Guidelines, and got a little carried away when seeing your name and posting more code. Please read or reread them. The link is in the first thread in the forum.

Also, the code you posted here is only partially correct. Please see the link that I posted in message 5.

Further, by doing this using a pointer and allocation on the heap method, the applicaiton will not recover necessarly all of the resources at termination, though the OS will under most cases (at least with open files and allocated memory) and is why I used the method I described.

Thanks for posting.


Adrian
May 30 '07 #9

P: 93
Girish Kanakagiri,

The Moderator who snipped out your code appologises. I talked to him/her. The reason was because you were posting a lot of code that was against the Posting Guidelines, and got a little carried away when seeing your name and posting more code. Please read or reread them. The link is in the first thread in the forum.

Also, the code you posted here is only partially correct. Please see the link that I posted in message 5.

Further, by doing this using a pointer and allocation on the heap method, the applicaiton will not recover necessarly all of the resources at termination, though the OS will under most cases (at least with open files and allocated memory) and is why I used the method I described.

Thanks for posting.


Adrian
Thanks for updating me about the posting Guide lines.

My Idea of allocating it on heap is mainly for the scope constraint.
Wanted to retain in heap till the end of the application and also
I can redirect to same memory location when second time onwards, call is
made to the Crt_Instance method.

Terminations, I left it for OS when the application is exhausted.
Thinking that it self is the requirement as given by OP.
Jun 1 '07 #10

AdrianH
Expert 100+
P: 1,251
Thanks for updating me about the posting Guide lines.
Yeah, somehow people just gloss over that one. ;)
My Idea of allocating it on heap is mainly for the scope constraint.
Wanted to retain in heap till the end of the application and also
I can redirect to same memory location when second time onwards, call is
made to the Crt_Instance method.
What scope constraint are you referring to? A static variable, whether it is a class or function scoped variable has a life span of the applicatoin.

The only problem with class scoped is that there is an initialisation ordering problem that occurs. You bypassed that problem using a pointer and initialising it on first use, which is how functoin static variables work. They too are only initialised on first use.

Terminations, I left it for OS when the application is exhausted.
Thinking that it self is the requirement as given by OP.
Possible, but cleanup can be a good idea too if you are connecting to things that are outside of the OS, otherwise they may have to time the connection out which may or may not occur on the app you are connecting to.

In my example lines 14-17 can be replace with:
Expand|Select|Wrap|Line Numbers
  1.   static A* pSingleton = new A(/* parameters */);
  2.   return *pSingleton;
  3.  
to acheive the same result. But then like yours, it would be cleaned up by the OS not the application.


Adrian
Jun 1 '07 #11

weaknessforcats
Expert Mod 5K+
P: 9,197
The singleton requires only one instance plus a global point of reference. Focus on reference. That does not mean a global variable! You never use global variables in professional C++.

Consider this:

Expand|Select|Wrap|Line Numbers
  1. class SysParms
  2. {         
  3.     protected:
  4.         SysParms();       //Only a SysParms member or subclass can call this
  5.  
  6.     public:
  7.                    virtual ~SysParms();
  8.            //The "official" access point. 
  9.                    static SysParms* Instance(const std::string& name);
  10.  
  11. };
  12.  
This means your singleton must derive from SysParms and note that the default constructor of SysParms is protected. That means you can't create a SysParms object.

You call the global point of reference to create your singleton. That is the Instance() function:

Expand|Select|Wrap|Line Numbers
  1. SysParms* SysParms::Instance()
  2. {
  3.     //"Lazy" initialization. Singleton not created until it's needed
  4.     if (!instance)
  5.     {
  6.         instance = new SysParms;
  7.     }
  8.     return instance;
  9. }
  10.  
The instance is located in an anonymous namespace which makes it inacessible outside the file with the namespace. Usually the file with the namespace contains the code for the Instance() function.

Expand|Select|Wrap|Line Numbers
  1. namespace
  2. {
  3.     SysParms* instance = 0;        //Address of the singleton
  4.  
  5. }
  6.  
So, the singleton is not created until it is needed by someone calling the Instance() method.

From here singletons get a little more involved.

You can create a registry of singletons (like and STL map) and store the "this" pointers in the registry. Now you can access the singletons by a key.

Refer to the book Design Patterns by Eric Fromm, et al, Addision-Wesley 1994 for more info.

I can provide an example using a registry if you are interested.
Jun 1 '07 #12

AdrianH
Expert 100+
P: 1,251
The singleton requires only one instance plus a global point of reference. Focus on reference. That does not mean a global variable! You never use global variables in professional C++.

Consider this:

Expand|Select|Wrap|Line Numbers
  1. class SysParms
  2. {         
  3.     protected:
  4.         SysParms();       //Only a SysParms member or subclass can call this
  5.  
  6.     public:
  7.                    virtual ~SysParms();
  8.            //The "official" access point. 
  9.                    static SysParms* Instance(const std::string& name);
  10.  
  11. };
  12.  
This means your singleton must derive from SysParms and note that the default constructor of SysParms is protected. That means you can't create a SysParms object.

You call the global point of reference to create your singleton. That is the Instance() function:

Expand|Select|Wrap|Line Numbers
  1. SysParms* SysParms::Instance()
  2. {
  3.     //"Lazy" initialization. Singleton not created until it's needed
  4.     if (!instance)
  5.     {
  6.         instance = new SysParms;
  7.     }
  8.     return instance;
  9. }
  10.  
The instance is located in an anonymous namespace which makes it inacessible outside the file with the namespace. Usually the file with the namespace contains the code for the Instance() function.

Expand|Select|Wrap|Line Numbers
  1. namespace
  2. {
  3.     SysParms* instance = 0;        //Address of the singleton
  4.  
  5. }
  6.  
So, the singleton is not created until it is needed by someone calling the Instance() method.

From here singletons get a little more involved.

You can create a registry of singletons (like and STL map) and store the "this" pointers in the registry. Now you can access the singletons by a key.

Refer to the book Design Patterns by Eric Fromm, et al, Addision-Wesley 1994 for more info.

I can provide an example using a registry if you are interested.
Except for the singleton registry, see upthread for everything you just stated. ;)

I would also not use a public destructor. Bad idea. This means that anyone can destroy the object.

Adrian
Jun 1 '07 #13

weaknessforcats
Expert Mod 5K+
P: 9,197
I would also not use a public destructor. Bad idea. This means that anyone can destroy the object.
oops.

The destructor shouldbe protected.
Jun 1 '07 #14

AdrianH
Expert 100+
P: 1,251
oops.

The destructor shouldbe protected.
What is going to be inheriting it that is going to delete it?

EDIT: Then of course if you do inherit from it, you are two singletons based on the same base, the base and the inheritor. I'm not sure if that is all that useful. It would have to use protected or private inheritance that's for sure.


Adrian
Jun 1 '07 #15

Post your reply

Sign in to post your reply or Sign up for a free account.