The Singleton design pattern is nowadays seen as an anti pattern. While in the past it has served the nice purpose of making sure that something exists only once, the sole purpose of a singleton has become a show stopper for proper (unit) testing and thus is being declared evil by many architects these days.
To understand why the Singleton design pattern is evil, we first need to understand the purpose of design patterns in common and that of the Singleton design pattern in particular plus what fundamental architectural design requirements these days need to be fulfilled when designing software.
Design patterns are used to model solutions for reoccuring problems in software design. These solutions are then named because names are much shorter than descriptions. The names of design patterns allow easy communication about design patterns as well as creating catalogues with indices about design patterns.
There are many well known design patterns, like Factory Method, Factory Class, Abstract Factory, Visitor, Mirror, Facade and many many more.
In a model, a Singleton is something which is class and instance at the same time. The requirement that is set for a Singleton thus is that there shall be only one instance of the Singleton's class. Therefore instantiation of the Singleton must be prevented.
A typical Singleton source code might look like this:
/** The Singleton class. */
public class MySingleton {
/** The instance. */
private static MySingleton instance = new MySingleton();
/** Private constructor, prevents any further instantiation. */
private MySingleton() {
}
/** Returns the instance of this Singleton.
* @return The instance of this Singleton.
*/
public static MySingleton getInstance() {
return instance;
}
} |
Please note that lazy initialization, multi-threading and other issues are beyond the scope of this discussion.
Unit testing, sometimes also referred to as component testing, is a fundamental part of modern software engineering. Unit testing helps increasing the software quality by finding bugs in an early development stage. When unit tests are maintained in a good manner, they can be easily executed over and over again, helping to prevent regression. Regression means that something that was already working fine broke, usually due to changes.
Changes lead to regression. But not applying changes to circumvent the risk of regression is the wrong approach. Software needs to be changed regularly, to increase its maintainability and to make the integration of new features for new requirements easier. That means we must find a different way to regression, and that is unit testing. The other approach would be to not change the software, but we want to change the software to integrate new features to compete on the market, don't we?
Unit testing is a well established process for increasing software quality. Unit tests are applied on a relatively low level. A single unit test uses a very small part of the software and verifies that it behaves as expected, i.e. as the requirements, the design, the architecture, the documentation or the contract suggest.
There are some requirements on unit testing which lead to some requirements in software design and software architecture.
A Singleton exists only once, by definition. This violates the test independence, which as we've seen is a fundamental requirement of unit testing.
Quite often, the assumption that it usually doesn't make sense to create further instances from a class apart from the first one is wrongly turned into a requirement that such further instances must be prevented. Why? Let's take a closer look.
Do you really know whether absolutely no user does not have a good reason to instantiate the class a second or third time? Apart from unit tests, there might be other occasions where a second instance might make sense which we just can't think of right now. Why place such restrictions on your class when you could live without? Let's see what we could do instead:
/** Class with default instance. */
public class ClassWithDefaultInstance {
/** The default instance. */
private static ClassWithDefaultInstance instance = new ClassWithDefaultInstance();
/** Create an instance of ClassWithDefaultInstance.
* Usually you will want to use the default instance,
* which can be retrieved with {@link #getInstance()}.
*/
public ClassWithDefaultInstance() {
}
/** Returns the default instance.
* @return The default instance.
*/
public static ClassWithDefaultInstance getInstance() {
return instance;
}
} |
Please note again that lazy initialization and threading issues are beyond the scope of this discussion.
In Java there is another issue with Singletons. In fact, Singletons are impossible in Java. If you create a Singleton and rely on the Singleton really being a Singleton, you fool yourself. It will always be possible to create more than one instance of the class. The trick is using the ClassLoader to load the class more than once. There will still be only one instance per class, but the class will be loaded more than once, and thus indirectly there will be more than one instance.
An OO model thus looks better without Singletons.