Singleton is anti-pattern
The article below describes the behavior of the Singleton
design pattern as an anti-pattern, where it violates the basic principle of
creating a single object.
We all are very much aware of Singletons, one of the main
Creational Design Patterns. It's a very widely and commonly used Design
Pattern. Most of you are aware of the advantages and the problems solved by the
pattern, but I am not going to deal with those features in this article.
What most of us fail to understand is that in most of the
cases, the Singleton is misused and acts as an anti-pattern. So let's try to
look at the scenarios where the Singleton design pattern works as an
anti-pattern.
·
Singletons are basically used as global
variables. Using global variables is an enemy of encapsulation because it
becomes difficult to define pre- and post-conditions for the client’s object
interface. The working of the interface can be handled from within, and not
from outside, the interface.
·
The use of Singletons makes it difficult to unit
test classes because classes must be loosely coupled, allowing them to be
tested individually.
·
When unit testing two classes, Singletons break
the Single Responsibility Principle because one class is implementing Singleton
and other is not. We need to pass in the Singleton as a parameter to the
constructor, allowing the tester to mock out the Singleton class easily. The
Singleton then does not has to enforce its own singularity. This can be done by
factory classes eliminating the global state.
·
Singletons are bad when used with
multi-threading because with just a single object, the options of threading are
limited.
·
Singletons make it easy to break stuff. A file
system is usually implemented as a singleton and, mostly, all the file
operations are performed under a single method. However, binding the team to
use just one common method to implement file operations makes it very difficult
to implement.
·
Singletons decrease performance. If we have a
number of lazily initialized Singletons, the compiler cannot fold multiple
SingletonDemo.getInstance() calls into one. This is because each call to
getInstance() will cause a branch instruction and possibly a cache mismatch.
·
Singletons promote tight coupling between
classes. Singletons tightly couple the code to the exact object type and remove
the scope of polymorphism.
·
Singletons do not complete what they are meant
to because a number of techniques — namely Java Reflection, serialization, etc.
— are available to create more than one instances of a Singleton class.
·
Using a static method to initialize Singleton
objects is considered a good approach implementing Singletons. But remember,
this approach forces the programmer to know the internal code structure of the
class, as static methods can be invoked only on class names. Moreover, unit
testing static methods is not an easy task using simple Mockito frameworks.
·
In the Agile world, we need to unit test even a
single functionality. One of the most important things about these unit tests
is that they must be independent of each other, making it difficult to
implement with Singletons.
·
Extending Singletons is not easy. A programmer
needs to use some kind of decorator pattern to change the behavior.
·
In a garbage collected system, Singletons can
become very tricky in regard to memory management.
·
Singletons can’t be used with clustering.
Conclusion
The use of Singletons should be a very careful and
calculated step because they can become a bottleneck during development and
debugging.
Instead of using classes, emphasize using enums for
implementing Singletons.
Enum for Singleton
public enum SingletonEnum {
INSTANCE;
int value;
public int GetValue() {
return value;
}
public void SetValue(int value) {
this.value = value;
}
}
Call for Singleton Enum
public class EnumDemo {
public static void Main(string[] args) {
SingletonEnum singleton = SingletonEnum.INSTANCE;
System.ConsoleWriteLine(singleton.GetValue());
singleton.setValue(2);
System.ConsoleWriteLine(singleton.GetValue());
}
}
Enum for Singleton
public enum SingletonEnum {
INSTANCE;
int value;
public int GetValue() {
return value;
}
public void SetValue(int value) {
this.value = value;
}
}
Call for Singleton Enum
public class EnumDemo {
public static void Main(string[] args) {
SingletonEnum singleton = SingletonEnum.INSTANCE;
System.ConsoleWriteLine(singleton.GetValue());
singleton.setValue(2);
System.ConsoleWriteLine(singleton.GetValue());
}
}
Comments