Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Singleton with parameters

I need a singleton class to be instantiated with some arguments. The way I'm doing it now is:

class SingletonExample {      private SingletonExample mInstance;      //other members...       private SingletonExample()      {       }       public SingletonExample Instance      {          get          {               if (mInstance == null)               {                   throw new Exception("Object not created");               }               return mInstance;          }      }       public void Create(string arg1, string arg2)      {          mInstance = new SingletonExample();          mInstance.Arg1 = arg1;          mInstance.ObjectCaller = new ObjectCaller(arg2);          //etc... basically, create object...      }  } 

The instance is created 'late', meaning I don't have all of the needed arguments on app startup.

In general I don't like forcing an ordering of method calls, but I don't see another way here. The IoC wouldn't resolve it either, since where I can register it in the container, I can also call Create()...

Do you consider this an OK scenario? Do you have some other idea?

edit: I know that what I wrote as an example it's not thread safe, thread-safe isn't part of the question

like image 912
veljkoz Avatar asked Nov 17 '10 10:11

veljkoz


People also ask

Can singleton class have parameters?

A parameter is assigned to the constructor of the singleton class type (as we did in step two). We initialize a public static getObject or getInstance function with a class object as the return value.

Why You Should Avoid singleton?

By using singletons in your project, you start to create technical debt. Singletons tend to spread like a virus because it's so easy to access them. It's difficult to keep track of where they're used and getting rid of a singleton can be a refactoring nightmare in large or complex projects.

What is the disadvantage of singleton?

Disadvantages of a Singleton PatternUnit testing is more difficult (because it introduces a global state into an application). This pattern reduces the potential for parallelism within a program, because to access the singleton in a multi-threaded system, an object must be serialized (by locking).


2 Answers

Singleton is ugly but since user whateva can't be bothered to correct his own code...

public class Singleton  {      private static Singleton _instance = null;       private static Object _mutex = new Object();      private Singleton(object arg1, object arg2)      {          // whatever     }       public static Singleton GetInstance(object arg1, object arg2)     {          if (_instance == null)          {            lock (_mutex) // now I can claim some form of thread safety...           {               if (_instance == null)                {                    _instance = new Singleton(arg1, arg2);               }           }          }          return _instance;     } }   

Skeet blogged about this years ago I think, it's pretty reliable. No exceptions necessary, you aren't in the business of remembering what objects are supposed to be singletons and handling the fallout when you get it wrong.

Edit: the types aren't relevant use what you want, object is just used here for convenience.

like image 80
annakata Avatar answered Sep 27 '22 21:09

annakata


A Singleton with parameters smells fishy to me.

Consider whateva's answer and the following code:

Singleton x = Singleton.getInstance("hello", "world"); Singleton y = Singleton.getInstance("foo", "bar"); 

Obviously, x==y and y works with x's creation parameters, while y's creation parameters are simply ignored. Results are probably... confusing at least.

If you really, really fell like you have to do it, do it like this:

class SingletonExample {      private static SingletonExample mInstance;      //other members...       private SingletonExample()      {  // never used         throw new Exception("WTF, who called this constructor?!?");      }      private SingletonExample(string arg1, string arg2)      {          mInstance.Arg1 = arg1;          mInstance.ObjectCaller = new ObjectCaller(arg2);          //etc... basically, create object...          }       public static SingletonExample Instance      {          get          {               if (mInstance == null)               {                   throw new Exception("Object not created");               }               return mInstance;          }      }       public static void Create(string arg1, string arg2)      {          if (mInstance != null)          {              throw new Exception("Object already created");          }          mInstance = new SingletonExample(arg1, arg2);                   }  } 

In a multithreading environment, add synchronisation to avoid race conditions.

like image 38
Erich Kitzmueller Avatar answered Sep 27 '22 21:09

Erich Kitzmueller