"Singleton" factories, ok or bad?

leeeroy picture leeeroy · Aug 16, 2009 · Viewed 30.6k times · Source

I've a lot of (abstract) factories and they're usually implemented as singletons.

Usually for the convenience of not having to pass them through layers who really have no business with using or knowing these factories.

Most of the times I only need to make a decision at startup of which factory implementation the rest of the code program, maybe through some configuration

it looks e.g. like

abstract class ColumnCalculationFactory { 
  private static ColumnCalculationFactory factory;

 public static void SetFactory(ColumnCalculationFactory f) {
         factory = f;
  }

  public static void Factory() {
         return factory;
  }

 public IPercentCalculation CreatePercentCalculation();
 public IAverageCalculation CreateAverageCalculation();
    ....

}

Someting do smell about this, I'm just not sure what - it's maybe more a disuised global than a singleton. It's not like there really really have to be only one factory ever creating ColumnCalculations - although my programs don't need more.

Is this considered best practuce ? Should I rather stuff these in some (semi) global AppContext class ? Something else(I'm not quite ready to switch to some larger IoC container, or spring.net quite yet btw) ?

Answer

Mark Simpson picture Mark Simpson · Aug 16, 2009

It really depends on what you're doing and the scope of your application. If it's just a fairly small app and it's never going to grow beyond this, then your current approach may well be fine. There is no universal "best" practice for these things. While I wouldn't recommend using singletons for anything other than stateless leaf methods and/or one-way calls (e.g. logging), dismissing it out of hand 'just because' it's a singleton isn't necessarily the right thing to do.

For anything other than trivial or prototype code, I personally like to explicitly use inversion of control with constructor injection, as it means all dependencies are accounted for and you don't get any 'surprises'. The compiler won't let you instantiate A without B and B without C. Singletons immediately bury these relationships -- you can instantiate A without B and B without C. When the call from A to B happens, you'll get a null reference exception.

This is especially annoying when testing, as you have to iteratively work backwards via runtime failures. When you test code, you're using the API just as a fellow coder would do, so it is indicative of the design problems with this approach. Constructor injection ensures this can never happen -- all of the dependencies are stated up front. The downside with constructor injection is that the configuration of your object graph is more complicated. This is mitigated through the use of an IoC container.

I guess what I'm trying to say is that if you've got to the point where you're considering using some kind of context object and a registry pattern, you may as well have a look at IoC containers. Going to the effort of rolling your own mutt version is probably a waste of time when you can use an established, free product like Autofac.