What are drawbacks or disadvantages of singleton pattern?

Viewed 597985

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?

Please support your answers with "facts, references, or specific expertise"

36 Answers

Paraphrased from Brian Button:

  1. They are generally used as a global instance, why is that so bad? Because you hide the dependencies of your application in your code, instead of exposing them through the interfaces. Making something global to avoid passing it around is a code smell.

  2. They violate the single responsibility principle: by virtue of the fact that they control their own creation and lifecycle.

  3. They inherently cause code to be tightly coupled. This makes faking them out under test rather difficult in many cases.

  4. They carry state around for the lifetime of the application. Another hit to testing since you can end up with a situation where tests need to be ordered which is a big no no for unit tests. Why? Because each unit test should be independent from the other.

Singletons solve one (and only one) problem.

Resource Contention.

If you have some resource that

(1) can only have a single instance, and

(2) you need to manage that single instance,

you need a singleton.

There aren't many examples. A log file is the big one. You don't want to just abandon a single log file. You want to flush, sync and close it properly. This is an example of a single shared resource that has to be managed.

It's rare that you need a singleton. The reason they're bad is that they feel like a global and they're a fully paid up member of the GoF Design Patterns book.

When you think you need a global, you're probably making a terrible design mistake.

Some coding snobs look down on them as just a glorified global. In the same way that many people hate the goto statement there are others that hate the idea of ever using a global. I have seen several developers go to extraordinary lengths to avoid a global because they considered using one as an admission of failure. Strange but true.

In practice the Singleton pattern is just a programming technique that is a useful part of your toolkit of concepts. From time to time you might find it is the ideal solution and so use it. But using it just so you can boast about using a design pattern is just as stupid as refusing to ever use it because it is just a global.

Misko Hevery, from Google, has some interesting articles on exactly this topic...

Singletons are Pathological Liars has a unit testing example that illustrates how singletons can make it difficult to figure out dependency chains and start or test an application. It is a fairly extreme example of abuse, but the point that he makes is still valid:

Singletons are nothing more than global state. Global state makes it so your objects can secretly get hold of things which are not declared in their APIs, and, as a result, Singletons make your APIs into pathological liars.

Where have all the Singletons Gone makes the point that dependency injection has made it easy to get instances to constructors that require them, which alleviates the underlying need behind the bad, global Singletons decried in the first article.

I think the confusion is caused by the fact that people don't know the real application of the Singleton pattern. I can't stress this enough. Singleton is not a pattern to wrap globals. Singleton pattern should only be used to guarantee that one and only one instance of a given class exists during run time.

People think Singleton is evil because they are using it for globals. It is because of this confusion that Singleton is looked down upon. Please, don't confuse Singletons and globals. If used for the purpose it was intended for, you will gain extreme benefits from the Singleton pattern.

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.

The singleton pattern is not a problem in itself. The problem is that the pattern is often used by people developing software with object-oriented tools without having a solid grasp of OO concepts. When singletons are introduced in this context they tend to grow into unmanageable classes that contain helper methods for every little use.

Singletons are also a problem from a testing perspective. They tend to make isolated unit-tests difficult to write. Inversion of control (IoC) and dependency injection are patterns meant to overcome this problem in an object-oriented manner that lends itself to unit testing.

In a garbage collected environment singletons can quickly become an issue with regard to memory management.

There is also the multi-threaded scenario where singletons can become a bottleneck as well as a synchronization issue.

A singleton gets implemented using a static method. Static methods are avoided by people who do unit testing because they cannot be mocked or stubbed. Most people on this site are big proponents of unit testing. The generally most accepted convention to avoid them is using the inversion of control pattern.

  1. It is easily (ab)used as a global variable.
  2. Classes that depend on singletons are relatively harder to unit test in isolation.

See Wikipedia Singleton_pattern

It is also considered an anti-pattern by some people, who feel that it is overly used, introducing unnecessary limitations in situations where a sole instance of a class is not actually required.[1][2][3][4]

References (only relevant references from the article)

  1. ^ Alex Miller. Patterns I hate #1: Singleton, July 2007
  2. ^ Scott Densmore. Why singletons are evil, May 2004
  3. ^ Steve Yegge. Singletons considered stupid, September 2004
  4. ^ J.B. Rainsberger, IBM. Use your singletons wisely, July 2001

I'm not going to comment on the good/evil argument, but I haven't used them since Spring came along. Using dependency injection has pretty much removed my requirements for singleton, servicelocators and factories. I find this a much more productive and clean environment, at least for the type of work I do (Java-based web applications).

There is nothing inherently wrong with the pattern, assuming it is being used for some aspect of your model which is truly single.

I believe the backlash is due to its overuse which, in turn, is due to the fact that it's the easiest pattern to understand and implement.

Singleton is a pattern and can be used or abused just like any other tool.

The bad part of a singleton is generally the user (or should I say the inappropriate use of a singleton for things it is not designed to do). The biggest offender is using a singleton as a fake global variable.

When you write code using singletons, say, a logger or a database connection, and afterwards you discover you need more than one log or more than one database, you’re in trouble.

Singletons make it very hard to move from them to regular objects.

Also, it’s too easy to write a non-thread-safe singleton.

Rather than using singletons, you should pass all the needed utility objects from function to function. That can be simplified if you wrap all them into a helper object, like this:

void some_class::some_function(parameters, service_provider& srv)
{
    srv.get<error_logger>().log("Hi there!");
    this->another_function(some_other_parameters, srv);
}

Too many people put objects which are not thread safe in a singleton pattern. I've seen examples of a DataContext (LINQ to SQL) done in a singleton pattern, despite the fact that the DataContext is not thread safe and is purely a unit-of-work object.

Recent article on this subject by Chris Reath 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

The problems with singletons is the issue of increased scope and therefore coupling. There is no denying that there are some of situations where you do need access to a single instance, and it can be accomplished other ways.

I now prefer to design around an inversion of control (IoC) container and allow the the lifetimes to be controlled by the container. This gives you the benefit of the classes that depend on the instance to be unaware of the fact that there is a single instance. The lifetime of the singleton can be changed in the future. Once such example I encountered recently was an easy adjustment from single threaded to multi-threaded.

FWIW, if it a PIA when you try to unit test it then it's going to PIA when you try to debug, bug fix or enhance it.

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.

Firstly a class and its collaborators should firstly 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.

Often software gets more complicated it makes sense to have multiple independent instances of the Singleton class with 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 it's 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 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.

Singletons aren't evil, if you use it properly & minimally. There are lot of other good design patterns which replaces the needs of singleton at some point (& also gives best results). But some programmers are unaware of those good patterns & uses the singleton for all the cases which makes the singleton evil for them.

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.

Some counterpoints from the author:

You are stuck if you need to make the class not single in the future Not at all - I was in this situation with a single database connection singleton that I wanted to turn into a connection pool. Remember that every singleton is accessed through a standard method:

MyClass.instance

This is similar to the signature of a factory method. All I did was update the instance method to return the next connection from the pool - no other changes required. That would have been far harder if we had NOT been using a singleton.

Singletons are just fancy globals Can't argue with that but so are all static fields and methods - anything that is accessed from the class rather than an instance is essentially global and I dont see so much pushback on the use of static fields?

Not saying that Singletons are good, just pushing back at some of the 'conventional wisdom' here.

The Singleton – the anti-pattern! by Mark Radford (Overload Journal #57 – Oct 2003) is a good read about why Singleton is regarded an anti-pattern. The article also discusses two alternatives design approaches for replacing Singleton.

This is what I think is missing from the answers so far:

If you need one instance of this object per process address space (and you are as confident as you can be that this requirement will not change), you should make it a singleton.

Otherwise, it's not a singleton.

This is a very odd requirement, hardly ever of interest to the user. Processes and address space isolation are an implementation detail. They only impact on the user when they want to stop your application using kill or Task Manager.

Apart from building a caching system, there aren't that many reasons why you'd be so certain that there should only be on instance of something per process. How about a logging system? Might be better for that to be per-thread or more fine-grained so you can trace the origin of messages more automatically. How about the application's main window? It depends; maybe you'll want all the user's documents to be managed by the same process for some reason, in which case there would be multiple "main windows" in that process.

It blurs the separation of concerns.

Supposed that you have a singleton, you can call this instance from anywhere inside your class. Your class is no longer as pure as it should be. Your class will now no longer operate on its members and the members that it receives explicitly. This will create confusion, because the users of the class don't know what is the sufficient information the class needs. The whole idea of encapsulation is to hide the how of a method from the users, but if a singleton is used inside the method, one will have to know the state of the singleton in order to use the method correctly. This is anti-OOP.

Off the top of my head:

  1. They enforce tight-coupling. If your singleton resides on a different assembly than its user, the using assembly cannot ever function without the assembly containing the singleton.
  2. They allow for circular dependencies, e.g., Assembly A can have a singleton with a dependency on Assembly B, and Assembly B can use Assembly A's singleton. All without breaking the compiler.
Related