Cleaning up a mess
in a project [Singleton standard] was used to instantiate classes that loaded data into memory when the program was started.
In fact, the Singleton nay serves to start data at the beginning of the program, but rather to ensure a single instance (within a context) of a certain object.
There, it does not matter if the object is instantiated at the beginning of the program (ager) or on the first call to the method (Lazy).
Two implementations
public class Singleton {
private static Singleton eagerInstance = new Singleton();
public static Singleton getEagerInstance() {
return eagerInstance;
}
private static Singleton lazyInstance;
public static Singleton getLazyInstance() {
if (lazyInstance == null) {
synchronized (Singleton.class) {
if (lazyInstance == null) {
lazyInstance = new Singleton();
}
}
}
return lazyInstance;
}
}
Instantiating the object at the beginning of the program (or loading the class) is simpler, because we don’t need to worry about synchronization. However, the resources used are allocated even if they are not used.
It allows to instantiate the object on demand saves resources in some cases, but can cause a certain delay in responding to the first customer who uses the resource and requires extra care with the competition. Yes, both of you if
s are required to ensure 100% that there is no chance to load the object twice in a concurrent call.
To Singleton or not to Singleton?
Now, think of the example ager and the following comment:
why not call a static method where load all this data into memory?
Loading the data in memory through a static method is practically what I did in the example above. So, at the end of the day, your implementation is still a Singleton.
On the other hand, if you access the instances directly by an attribute, for example Singleton.instance
, then it really isn’t about the Singleton standard.
And this brings several disadvantages, which go beyond the disadvantages of the Singleton standard itself, such as the encapsulation break and the high coupling between implementations.
Considerations
Ultimately, every design standard is expendable.
Those who read the Gof carefully should have already noticed that the most cited side effect in the patterns is the increase in complexity and the number of classes.
The truth is that there are much more direct ways to solve problems. The big difference between not using patterns and using them (properly) can be observed in the long run.
Solving a problem more simply and directly can cause an even bigger problem from a maintenance point of view. For example, using a static attribute as mentioned above can cause serious problems if the way the system works changes. Imagine if tomorrow he’s no longer a Singleton, but needs to be a ThreadLocal
(Singleton per thread). Severe errors may also emerge after load, performance and concurrency tests that require synchronization of the recovered object.
Finally, let’s consider the last statement:
I can’t think of any example where it’s not possible to replace any Singleton implementation with a simple use of static members.
In general, this is because there is no difference. The Singleton standard is just a formalization of how to properly access a static attribute.
Great answer! The last sentence cleared my question. My mistake was to take the Singleton standard as a rule, like "I need to implement it somewhere in my code!".
– Gustavo Piucco