views:

825

answers:

3

Hello,

I'm implementing a notification framework for one of my projects. As i want it to be very generic, the user can use several transport layers, so that he doesn't really need to care about using one delivery method (lets say WCF) or another (for eg ActiveMQ). The interface the user has access is of course independent of the delivery method (WCF or ActiveMQ). Still, the two classes (consumer and producer) implements singletons, so they actually use default constructors (meaning, no parameters). My problem is that i would like to have one parameter, the delivery method the user want to use. But as far as i know, singleton only use default constructors? which is normal, as there should be no point of using singletons with parameters. So, what are my options here? not to create a singleton? create a method to set the delivery method?

Thank you very much for your help,

Sebastian

+3  A: 

You can certainly have parameters with singletons, except instead of passing the parameter into a constructor, you are passing it into the getInstance() method. Your overridden constructor needs to be private of course for a true singleton implementation. My example is written in Java but applies for C# as well.

Example:

Singleton s = Singleton.getInstance(42);

In the Singleton code:

private Singleton() {

}

private Singleton(int num) {
   //set num
}

public getInstance(int num) {
  //singleton code (calls the private non-default constructor if an object 
  //does not already exist) 
}
AlbertoPL
What happens or what does it mean if, later in the lifetime of the program, someone invokes `Singleton.getInstance(43);`?
ChrisW
It really would depend on the details of the implementation. If the object can only be instantiated once with a single number and then never changed, then the method would return the original object created. If 43 should be a different object altogether, the Singleton class in my example could hold an array of all the Singletons created and check the array. Either way seems weird though.
AlbertoPL
It would look more like a Factory in stead of a Singleton.
Ikke
Certainly, and I should point out that this is not the best use of a Singleton. The Singleton should only be used for stateless objects of which you'll only need one.
AlbertoPL
Why do you say that a singleton should be stateless? Isn't a singleton basically just a global (stateful) variable? A singleton might be used for, for example, keeping a list of all the current instances of something.
ChrisW
Apart from Singleton, a related Pattern is a 'Flyweight', whose state is immutable.
ChrisW
There are many debates over the proper use of the Singleton. In fact, some argue that the Singleton pattern is really an anti-pattern. You're right, a Singleton can be a global stateful object/class, but that state should not ever really change. It's hard to justify the Singleton pattern for a class/object that will be changing state.
AlbertoPL
A: 

There are some dependency injection frameworks like Spring.Net which might help you. You can effectively pass a parameter in a configuration file for your singletons constructor.

Link to a Spring Framework example

Might I suggest that if you have two different behaviours required of your singleton that you might want to subclass. That way you get the behaviour that you want by calling the singleton of the class behaviour you want.

Spence
A: 

You can do this easily with a dependency injection framework. I have a similar construct in my current project using MEF. All that's required is to use the constructor injection options, and add that assembly and the requested dependency's assembly to the catalog, and it wires it up correctly.

Another option is to have some form of initialize function that takes your option, and constructs the singleton instance. Instead of constructing it on first access, you can construct it during the initialization call. The downside here is that you need to make sure to initialize your singleton before you use it (typically at program start, using a config file).

A similar, but less error-prone option, is to just have the singleton lazy initialize, and give it a "default" option. Allow the caller to set a static property to alter which option is constructed, so if it's set prior to the singleton's construction, you'll get a different default. This can be confusing, though, since again, you need to make sure you set the property before accessing the singleton, or you'll get unexpected behavior.

Reed Copsey