« FITC Call out | Main | Flexities »

Singleton vs Static

My Outlook has been getting a serious workout on the topic of Singleton vs Static. These kinds of discussions typically get started by Derek Vadneau who usually shoots me off an email with question that always gets me thinking. And true to my own nature, I typically respond without thinking and it snowballs from there. The question "Why would you use a Singleton over a Static, and vise versa?" is no different.

Immediately my initial reaction was - well, Static classes have no instance level variables. They are best suited for utility type classes where you can group like functions together - like a String utility class. Or they are good if you want to have them as an entry point for a factory type of approach where they take care of generating the items - I use this terminology loosely, but something like the Alert class might be a good example of what I mean. Singletons and Statics both provide a "global" type of entry point in terms of referencing them, but a singleton is more effective if you need to keep track of stateful items.

Those were my first reactions to that question. I asked a bunch of people and the responses were varied. Tony had proposed the idea of stateless vs stateful as a distinction between the two. Static classes, altho they can retain information about state are better off retaining information that is stateless. Singletons are better of taking care of information that is stateful. Of course, all this is just paraphasing.:)

I then png'd a developer I had the great pleasure of working with on the SNL merger model, Brian. This dude knows his stuff and its nice to get a perspective that isn't flash based or even biased ;). And his explanation was soooo good that I am just going to dump it here and hope that he doesn't shoot me one day for posting this:

Looking at a practical example:

public SomeClass {

public static int doSomething(int a, int b) {
return a + b;
}
}

public class AnotherClass {
private AnotherClass instance = new AnotherClass();

private AnotherClass() { // private constructor so no one else can instantiate objects }

public static AnotherClass GetInstance() {
return instance; // classic singleton
}

public int doSomething(int a, int b) {
return a + b;
}
}

There is no functional difference between the following:
int x = SomeClass.doSomething(1,2);
int y = AnotherClass.GetInstance().doSomething(1,2);

Personally, I feel the second construct (what you call "singleton") is more flexible because it hides object management and subclassing from the application layer. For example, I can make the following changes rather easily:

// Converts from singleton to factory
public static AnotherClass GetInstance() {
return new AnotherClass(); // factory method, returns a new object instance each time
}

// Change the implementation altogether
public static AnotherClass GetInstance() {
return new AnotherClassSubclass(); // abstract factory method, returns a new implementation altogether
}

public class AnotherClassSubclass extends AnotherClass {
public int doSomething(int a, int b) {
return a * b;
}
}

Both are very significant changes but we can effect them WITHOUT changing the code.
int y = AnotherClass.GetInstance().doSomething(1,2); // this line of code still works whether you use singletons, factory methods, or abstract factory methods

If you wanted to accomplish the same thing using static methods, you would definitely have to change the code
SomeClass s = new SomeClass(); // explicitly declare a new instance
int x = s.doSomething(1,2);

or
int x = SomeClass.doSomethingDifferent(1,2); // add another static method to multiply instead of add

or
int x = SomeOtherClass.doSomething(1,2); // add another class altogether if you want keep the same method signature and multiply instead of add

These differences are extremely subtle but they do impact how resilient the system will hold up after years of subtle changes, new features, enhancements, etc. Most developers dislike system maintenance and I feel the biggest reason is because systems aren't really designed to be maintained. By incorporating the "singleton" pattern above, I've abstracted object creation and typing away from my core business logic which is critical to long-term maintenance.

In short, while there isn't much of a difference in terms of functionality, there is a pretty significant difference between these approaches in terms of flexibility. From experience, things will change over time and if I can push my changes to the fringe of the app and leave the core app logic unchanged, I feel better about my design. I only use static classes if I'm convinced the details won't change over time -- a utility class for parsing strings is a good example. If the code contains business logic, which is likely to change over time, I prefer the flexibility of the singleton approach."

--------
Good advice I'd say. Thoughts, comments, discussion on this, as always, is welcome and encouraged.

Posted by bitch at April 7, 2006 06:38 PM

Comments

Good article. I agree with Tony on state vs. stateless being the primary distinction. Your example shows how using a singleton insulates against future change. My question is: If a class has no state, is there a practical use for a factory?

Posted by: Robert Penner at April 7, 2006 11:52 PM

I totally agree with anything said above. I'd actually go a step further and abandon Singletons altogether and use an application context instead (the Springframework offers support for this and the As2lib will in the next release). This gives you even more flexibility and ease of maintenance.

Static classes also cannot take advantage of inheritance and cannot implement interfaces.

I too wrote an article about a similar topic some time ago: http://www.simonwacker.com/blog/archives/000079.php (I don't agree with everything I wrote in the article and the implementation is also rather naive but the core statement is still true)

Cheers,
Simon

Posted by: Simon Wacker at April 9, 2006 04:54 PM

bits of this I'm still getting used to but I cam across something I thought was wierd:

"QuestionHelper" is a class with (only) static methods.

QuestionHelper QHelp = new QuestionHelper();
QHelp.Host = Request.ServerVariables["HTTP_HOST"];
string ResourcePath = QuestionHelper.GetServerPath(args);

it just feels wierd to set a property of an instance to then run the static methods. is doing it this way normal?


Posted by: a confused person at April 10, 2006 06:56 AM




Remember Me?