singleton pattern - design question

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • adina
    New Member
    • Mar 2007
    • 9

    singleton pattern - design question

    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
  • sicarie
    Recognized Expert Specialist
    • Nov 2006
    • 4677

    #2
    Originally posted by adina
    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?

    Comment

    • Steven22
      New Member
      • May 2007
      • 1

      #3
      Originally posted by adina
      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.

      Comment

      • Girish Kanakagiri
        New Member
        • May 2007
        • 93

        #4
        Change in the data member

        Originally posted by adina
        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 !!!
        Last edited by AdrianH; May 29 '07, 01:41 PM. Reason: Please use [code=cpp][/code] tags for readability.

        Comment

        • AdrianH
          Recognized Expert Top Contributor
          • Feb 2007
          • 1251

          #5
          A singleton pattern is simple to do if you do it right. It can be disastrous if done wrong.

          [code=cpp]
          class A {
          A(/* parameters */) {
          /* init code */
          }

          ~A() {
          /* destruction code */
          }

          A(A const&);

          public:
          A& instance() {
          static A singleton(/* parameters */);
          // or if no parameters use
          static A singleton;
          return singleton;
          }
          };
          [/code]
          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

          Comment

          • AdrianH
            Recognized Expert Top Contributor
            • Feb 2007
            • 1251

            #6
            Originally posted by Girish Kanakagiri
            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

            Comment

            • Girish Kanakagiri
              New Member
              • May 2007
              • 93

              #7
              Originally posted by AdrianH
              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

              Comment

              • Girish Kanakagiri
                New Member
                • May 2007
                • 93

                #8
                Originally posted by adina
                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 -----

                [code=cpp]class ConfigManager
                {
                private:
                ConfigManager(t ype parameter);
                // some more functions and data members

                public:
                static ConfigManager* inst_;
                static ConfigManager* crt_inst(type parameter);
                // some more data members and functions
                };

                ConfigManager:: ConfigManager(t ype parameter)
                {
                // Fill up the body
                }

                ConfigManager* ConfigManager:: inst_ = 0;

                ConfigManager* crt_inst(type parameter)
                {
                if(inst_ == 0)
                {
                inst_ = new ConfigManager(p arameter); // parameter

                is same which is passed to crt_inst
                }
                return inst_;
                }[/code]

                Implementation part ------

                [code=cpp]ConfigManager *cptr;
                cptr = ConfigManager :: crt_inst(parame ter);

                /* pass the parameter which is required for the constructor, but

                remember only first time passed parameter will be

                retained since instance of the class will be only one */

                // Now cptr points to instance of ConfigManager class, make use of it
                [/code]
                Regards,
                Girish Kanakagiri
                Last edited by AdrianH; May 30 '07, 03:55 PM. Reason: Please use [code=cpp][/code] tags for improved readability

                Comment

                • AdrianH
                  Recognized Expert Top Contributor
                  • Feb 2007
                  • 1251

                  #9
                  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

                  Comment

                  • Girish Kanakagiri
                    New Member
                    • May 2007
                    • 93

                    #10
                    Originally posted by AdrianH
                    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.

                    Comment

                    • AdrianH
                      Recognized Expert Top Contributor
                      • Feb 2007
                      • 1251

                      #11
                      Originally posted by Girish Kanakagiri
                      Thanks for updating me about the posting Guide lines.
                      Yeah, somehow people just gloss over that one. ;)
                      Originally posted by Girish Kanakagiri
                      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.

                      Originally posted by Girish Kanakagiri
                      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:
                      [code=cpp]
                      static A* pSingleton = new A(/* parameters */);
                      return *pSingleton;
                      [/code]
                      to acheive the same result. But then like yours, it would be cleaned up by the OS not the application.


                      Adrian

                      Comment

                      • weaknessforcats
                        Recognized Expert Expert
                        • Mar 2007
                        • 9214

                        #12
                        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:

                        [code=cpp]
                        class SysParms
                        {
                        protected:
                        SysParms(); //Only a SysParms member or subclass can call this

                        public:
                        virtual ~SysParms();
                        //The "official" access point.
                        static SysParms* Instance(const std::string& name);

                        };
                        [/code]

                        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:

                        [code=cpp]
                        SysParms* SysParms::Insta nce()
                        {
                        //"Lazy" initialization. Singleton not created until it's needed
                        if (!instance)
                        {
                        instance = new SysParms;
                        }
                        return instance;
                        }
                        [/code]

                        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.

                        [code=cpp]
                        namespace
                        {
                        SysParms* instance = 0; //Address of the singleton

                        }
                        [/code]

                        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.

                        Comment

                        • AdrianH
                          Recognized Expert Top Contributor
                          • Feb 2007
                          • 1251

                          #13
                          Originally posted by weaknessforcats
                          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:

                          [code=cpp]
                          class SysParms
                          {
                          protected:
                          SysParms(); //Only a SysParms member or subclass can call this

                          public:
                          virtual ~SysParms();
                          //The "official" access point.
                          static SysParms* Instance(const std::string& name);

                          };
                          [/code]

                          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:

                          [code=cpp]
                          SysParms* SysParms::Insta nce()
                          {
                          //"Lazy" initialization. Singleton not created until it's needed
                          if (!instance)
                          {
                          instance = new SysParms;
                          }
                          return instance;
                          }
                          [/code]

                          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.

                          [code=cpp]
                          namespace
                          {
                          SysParms* instance = 0; //Address of the singleton

                          }
                          [/code]

                          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

                          Comment

                          • weaknessforcats
                            Recognized Expert Expert
                            • Mar 2007
                            • 9214

                            #14
                            Originally posted by AdrianH
                            I would also not use a public destructor. Bad idea. This means that anyone can destroy the object.
                            oops.

                            The destructor shouldbe protected.

                            Comment

                            • AdrianH
                              Recognized Expert Top Contributor
                              • Feb 2007
                              • 1251

                              #15
                              Originally posted by weaknessforcats
                              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

                              Comment

                              Working...