Alex Rivera | Logout

What are drawbacks or disadvantages of the singleton pattern?

Asked 2008-09-26T06:02:00.727
2189

The singleton pattern is a fully paid up member of the GoF's patterns book, but it lately seems rather orphaned by the developer world. I still use quite a lot of singletons, especially for factory classes, and while you have to be a bit careful about multithreading issues (like any class actually), I fail to see why they are so awful.

Stack Overflow especially seems to assume that everyone agrees that Singletons are evil. Why?

Edit
Report

6 Answers

76

One rather bad thing about singletons is that you can't extend them very easily. You basically have to build in some kind of decorator pattern or some such thing if you want to change their behavior. Also, if one day you want to have multiple ways of doing that one thing, it can be rather painful to change, depending on how you lay out your code.

One thing to note, if you do use singletons, try to pass them in to whoever needs them rather than have them access it directly... Otherwise, if you ever choose to have multiple ways of doing the thing that singleton does, it will be rather difficult to change as each class embeds a dependency if it accesses the singleton directly.

So basically:

public MyConstructor(Singleton singleton) {
    this.singleton = singleton;
}

rather than:

public MyConstructor() {
    this.singleton = Singleton.getInstance();
}

I believe this sort of pattern is called dependency injection and is generally considered a good thing.

Like any pattern though... Think about it and consider if its use in the given situation is inappropriate or not... Rules are made to be broken usually, and patterns should not be applied willy-nilly without thought.

answered 2008-09-26T06:17:12.377
19

I'd like to address the four points in the accepted answer, and hopefully someone can explain why I'm wrong.

  1. Why is hiding dependencies in your code bad? There are already dozens of hidden dependencies (C runtime calls, OS API calls, and global function calls), and singleton dependencies are easy to find (search for instance()).

    "Making something global to avoid passing it around is a code smell." Why isn't passing something around to avoid making it a singleton a code smell?

    If you're passing an object through 10 functions in a call stack just to avoid a singleton, is that so great?

  2. single responsibility principle: I think this is a bit vague and depends on your definition of responsibility. A relevant question would be, why does adding this specific "responsibility" to a class matter?

  3. Why does passing an object to a class make it more tightly coupled than using that object as a singleton from within the class?

  4. Why does it change how long the state lasts? Singletons can be created or destroyed manually, so the control is still there, and you can make the lifetime the same as a non-singleton object's lifetime would be.

Regarding unit tests:

  • not all classes need to be unit tested

  • not all classes that need to be unit tested need to change the implementation of the singleton

  • if they do need be unit tested and do need to change the implementation, it's easy to change a class from using a singleton to having the singleton passed to it via dependency injection.

answered 2010-04-07T13:31:48.510
9

A recent article on this subject by Chris Reath is at Coding Without Comments.

Note: Coding Without Comments is no longer valid. However, the article being linked to has been cloned by another user.

Link

answered 2008-10-09T08:18:15.497
6

Firstly, a class and its collaborators should perform their intended purpose rather than focusing on dependents. Lifecycle management (when instances are created and when they go out of scope) should not be part of the classes responsibility. The accepted best practice for this is to craft or configure a new component to manage dependencies using dependency injection (DI).

Often software gets more complicated. It makes sense to have multiple independent instances of the Singleton class with a different state. Committing code to simply grab the singleton is wrong in such cases. Using Singleton.getInstance() might be OK for small simple systems, but it doesn't work/scale when one might need a different instance of the same class.

No class should be thought of as a singleton, but rather that should be an application of its usage or how it is used to configure dependents. For a quick and nasty, this does not matter. Just luke hard coding, say file paths, does not matter, but for bigger applications, such dependencies need to be factored out and managed in a more appropriate way using DI.

The problems that singleton cause in testing is a symptom of their hard coded single usage case/environment. The test suite and the many tests are each individual and separate something that is not compatible with hard coding a singleton.

answered 2009-04-28T01:14:39.850
5

Because they are basically object-oriented global variables, you can usually design your classes in such a way so that you don't need them.

answered 2008-09-26T06:05:36.397
4

A pattern emerges when several people (or teams) arrives at similar or identical solutions. A lot of people still use singletons in their original form or using factory templates (good discussion in Alexandrescu's Modern C++ Design). Concurrency and difficulty in managing the lifetime of the object are the main obstacles, with the former easily managed as you suggest.

Like all choices, Singleton has its fair share of ups and downs. I think they can be used in moderation, especially for objects that survive the application life span. The fact that they resemble (and probably are) globals have presumably set off the purists.

answered 2008-09-26T06:14:25.020

Your Answer