Tuesday, September 28, 2004

singleton anti-pattern

At first, Singleton was introduce in GOF legendary book as one of the creational design pattern. Singleton design pattern helps to ensure that there will only be one instance of the Singleton class, for each JVM. While the Singleton pattern may be useful for certain types of classes, e.g. constant classes, class loaders, etc., it may not be appropriate for other type of classes.

But now, it's suggested that the usage of this class should be limited to those certain types of classes, because the Singleton pattern makes it almost impossible for the class (and possibly all other classes which depend on it) to be testable. It's very hard to subclass, or to create a mock object for a Singleton class.

It's interesting to keep adapting to implement Test-Driven Development.. :D

Further Reading:
Refactoring: Improving the Design of Existing Code
Design Patterns
Head First Design Patterns

1 comment:

  1. See my related blog entry called Singetons Considered Evil / Stupid.

    To save you the trouble, I've pasted the text below but go see the original in order to follow the links:

    I just came across >>Steve Yegge's rant called >>Singleton Considered Stupid and couldn't agree more. In fact, I've had >>more than a >>few >>rants on the same subject myself.

    Here are some of the highlights:

    "*Stateful* Singletons" are evil; they are just Object Oriented global variables. "Stateless Singletons" which are just used to avoid creating multiple instances of an Object with no instance variables, are fine.

    Statics values do have a purpose: they often afford short-term convenience, but at the cost of loosing re-usability and re-composability. Once you use a static you restrict yourself to only having a single instance of that item or whatever else depends on it.

    Fortunately in Java statics really aren't global to the JVM but only to the ClassLoader so you can work around this problem by using multiple class-loaders. It would be better however if you didn't have to. Inversion of Control or Environmental Acquisition systems are the solution (Java even has one built in the java.beancontext package but it is a bit verbose and easier solutions are available).

    The software industry has long hoped to establish a level of software re-use through componentization, much like the electronics and other industries. Unfortunately software components haven't succeeded as expected. The reason for this failure is the simple static or global variable. Only in software do individual components have a "magical" connection to this shared pool of global or static information or services. In all other fields, components, be it CPU or carburetor, only have access to what they’re explicitly connected to. Because of this limitation they are guaranteed to be re-usable and re-composable. I can use a given CPU in a computer or a DVD player and I can put two tail pipes on a car if I want. Software on the other hand has all sorts of artificial restrictions. Try to instantiate two instances of your favourite ORB (because you want to be configured with different hostnames of socket layers on different networks for example), or database driver or logging package. Even having one part of your application use a different System.out than the other can be a problem. Software components which rely on globals being one way or another are potentially excluding other software from running (especially another instance of themselves). Globals/Statics are holding back the entire software industry (or rather, the people who use them are); and that’s why I classify them as "evil".


    I find the Singleton pattern to be really dishonest; nobody really uses Singletons to enforce singularity, but rather to provide convenient accessibility. A Singleton is an "OO global" so it's convenient because you have access to it from anywhere within your system. If we were being honest it would be called a "Locator", "Accessor", or even "Global"! I've asked around and nobody could think of a legitimate need for Singletons.

    I've compiled a list of alternatives to globals at Context.