Tuesday, December 12, 2006

Prefer Singletons to Static classes

It's a common scenario: you have some core facade class with a load of stateless methods on it that delegate activity down to other layers. There didn't seem much point in having the overhead of instantiating the class to use the methods, so you made all the methods static. You've made a static class.

Trouble is, static classes just aren't as flexible as the alternative: a singleton. For example:

* Static classes can't implement interface contracts
* Static classes can't be passed around or used polymorphically
* Inheritance of static classes is a minefield
* You can't make static members virtual or abstract.

This might not be an issue straight up - in many cases it may never be an issue at all - but when it does you'll be kicking yourself.

Take the scenario where you decide somewhere along the line that your facade isn't the be-all-and-end-all, and that you want to swap implementations in different circumstances. You don't want your objects to know about it, so you refactor the facade into some kind of proxy-by-composition. Still you're tied to having only one implementation active at any one time.

By contrast if you'd started as a singleton, it's pretty easy to change which subclass gets setup on the singleton. Its also far easier to migrate to a dependency-injection type architecture later down the line to support multiple implementations being used in parallel (this also then decouples the objects from the facade/singleton, which is a benefit in plugin-style architectures). And it's far easier to refactor some of the functionality out of the class into a base class, and start replicating your facade functionality in other scenarios.

On a more mundane point, when setting up a static facade you're doing work in the static class constructor. When this throws, it throws TypeInitializationException. With a singleton you get the choice - lazy init via static field init (still throws TypeInitializationException), or via first-property access, which will throw an exception you'll have a chance of debugging.

Go the singleton straight off (a rule I've once again re-learnt the hard way).

1 comment:

ether said...

Completely agree. I've run into the same issue of having a static class and needing more. Worst case scenario was that suddenly state needed to be kept in one of these objects, but i couldn't redefine its interface, since it was live. So each static accessor grabbed an internal singleton and called a private "internal_" version of the accessor to get the value from the stateful singleton. Had I made the whole thing a singleton to start with i would have avoided that mess.

Popular Posts