The Singleton Pattern
The singleton design pattern is a pattern which limits the number of objects that can be instantiated to one. This can come in handy in many situations; for example, consider a web application which connects to a database server. Instead of opening several database connections, it would be a good idea to reuse the same connection for all requests. This can be accomplished by wrapping the database connection within a class that uses the singleton pattern. Another example could be a logging class. Instead of having several objects writing to the same logging directory, the same object could be used for this purpose.
The singleton pattern first and foremost accomplishes this by not exposing a public constructor. As you might suspect, this means that an object cannot be instantiated with the traditional approach, as shown below.
// This will not work if the DatabaseConnection class implements the singleton pattern
DatabaseConnection dbc = new DatabaseConnection();
Instead, a public method will be available, which returns an instance of the class. This method is by convention called getInstance(). This method will return an existing object if one exists and instantiate and return one otherwise. Because the constructor is private, only the class itself can use it to instantiate objects. Let us first see how the singleton pattern is implemented and then walk through it afterwards. The implementation below is in Java, but the same code will work in C#, and the same principles apply to other languages as well.
public class DatabaseConnection {
private static DatabaseConnection instance;
private DatabaseConnection() {
}
public static DatabaseConnection getInstance() {
if (this.instance == null) {
this.instance = new DatabaseConnection();
}
return this.instance;
}
}
In the class above, we have a private variable or field of the same type as the class. This is used to hold the single instance of the class, which in this case is a database connection. To get a database connection, simply do like so:
DatabaseConnection dbc = DatabaseConnection.getInstance();
The getInstance() method is also very straightforward. It is public as it is what will be used by other classes to provide an instance of the class. You should also note that it is static. This means that the method can be called just by using the class name as in the example above; that is, without having instantiated an object. This is necessary because we cannot use the traditional approach for instantiation, as previously discussed. Therefore we could never call getInstance() if it was not static.
The first thing the method does is to check if an object (a connection in this case) has already been created. If so, all we have to do is to simply return it, instead of creating a new one. This is where the magic really happens, because by doing this, it is impossible for more than one instance to be created. Should there be no instance already, which would be on the first call, then an instance will be created and stored in the instance variable. This same instance will then be returned.
Critique and disadvantages of the singleton pattern
While the above seems great and exactly what you need, there are a few things to consider before blindly going with the singleton approach. Some of the common counterarguments of the singleton pattern are summarized below.
-
Dependencies are hidden within the code and are not exposed by the interface. Therefore, using the interface will not reveal dependencies without inspecting the code. For instance, a method may make use of a database connection to fetch data. This is often accomplished by using the singleton pattern as shown previously. However, nothing in the method signature (e.g. its parameters) show this dependency, so users of this method will likely not expect this dependency. Instead, if a database connection was passed to the method as a parameter, this dependency would be known by the user of the method. While the singleton approach may be more convenient rather than passing objects around, it tends to hide code dependencies – at least in many situations.
-
Generally speaking, global variables are no good and should be avoided as much as possible. For the same reason, one can argue that singletons should be avoided as well, because what is the difference really? Singleton provides a convenient way of accessing a variable throughout an application (or part of one) while limiting the instances of one. Using globals can easily lead to a maintenance nightmare. Using singleton can also reduce maintainability because a lot of code can quickly depend on the use of the pattern.
The code is thereby less flexible, which is especially negative when using agile software development. In agile development, code is refactored and changed to adapt to changes in requirements. When using the singleton pattern, however, one could argue that today’s requirement limits those of the future. Why limit an application to one database connection or one logger instance when you might need two a month later?
-
The testability is reduced because the state of the singleton object is preserved throughout its lifetime and therefore between unit tests. This can lead to situations where one test may fail due to the failure of a preceding test.
-
Singletons are relatively difficult to make thread safe in a multithreaded environment. This adds additional complexity to the application.
For more thorough explanations of the disadvantages of the singleton pattern, we recommend reading the two articles linked below by Jesper Alf Dam and Brian Button, respectively.
Singletons: Solving problems you didn’t know you never had since 1995
One comment on »The Singleton Pattern«
I never considered that it’s harder to maintain and the dependency thing is a good point… especially with high traffic where it’s important to know if a function uses I/O.