Some hold that the Singleton Pattern is always an anti-pattern. What do you think?
- Anybody can ask a question
- Anybody can answer
- The best answers are voted up and rise to the top
There are either too many possible answers, or good answers would be too long for this format. Please add details to narrow the answer set or to isolate an issue that can be answered in a few paragraphs.If this question can be reworded to fit the rules in the help center, please edit the question.
The two main criticisms of Singletons fall into two camps from what I've observed:
As a result of both of these, a common approach is to use create a broad container object to hold a single instance of these classes and only the container object modifies these types of classes while many other classes can be granted access to them to use from the container object.
I agree that it is an anti-pattern. Why? Because it allows your code to lie about its dependencies, and you can't trust other programmers to not introduce mutable state in your previously immutable singletons.
A class might have a constructor that only takes a string, so you think it is instantiated in isolation and does not have side effects. However, silently, it is communicating with some sort of public, globabally available singleton object, so that whenever you instantiate the class, it contains different data. This is a big problem, not only for users of your API, but also for the testability of the code. To properly unit-test the code, you need to micro-manage and be aware of the global state in the singleton, to get consistent test results.
The Singleton pattern is basically just a lazily initialized global variable. Global variables are generally and rightly considered evil because they allow spooky action at a distance between seemingly unrelated parts of a program. However, IMHO there is nothing wrong with global variables that are set once, from one place, as part of a program's initialization routine (for example, by reading a config file or command line arguments) and treated as constants thereafter. Such use of global variables is different only in letter, not in spirit, from having a named constant declared at compile time.
Similarly, my opinion of Singletons is that they're bad if and only if they are used to pass mutable state between seemingly unrelated parts of a program. If they don't contain mutable state, or if the mutable state that they do contain is completely encapsulated so that users of the object don't have to know about it even in a multithreaded environment, then there's nothing wrong with them.
Why do people use it?
I have seen quite a number of singletons in the PHP world. I don't remember any use case where I found the pattern to be justified. But I think I got an idea about the motivation why people did use it.
The typical implementation is a class with a private constructor, and a static instance variable, and a static getInstance() method with lazy instantiation.
In addition to the problems mentioned above, this bites with the single responsibility principle, because the class does control its own instantiation and life cycle, in addition to the other responsibilities that the class already has.
In many cases, you can achieve the same result without a singleton, and without global state. Instead, you should use dependency injection, and you might want to consider a dependency injection container.
However, there are use cases where you have the following valid requirements remaining:
So, here is what you can do in this case:
(Do we still call this a singleton? I leave this to the comment section..)
Personally I will use singletons when I need 1, 2, or 3, or some limited amount of the objects for the particular class in question. Or I want to convey to the user of my class that I do not want multiple instances of my class being created for it to function properly.
Also I will only use it when I need to use it almost everywhere in my code and I don't want to pass an object as a parameter to each class or function that needs it.
In addition I will only use a singleton if it does not break another function's referential transparency. Meaning given some input it will always produce the same output. I.e. I don't use it for global state. Unless possibly that global state is initialized once and never changed.
As for when not to use it, see the above 3 and change them to the opposite.