There are a lot of blogs and discussion forums about this issue and you can find some really crazy comments and recommendations. But when do we use a singleton pattern??, in my opinion you have to consider these points (they all should happen):
1) You NEED only one instance of the class. For example, you need to synchronize the access to a shared resource
2) The singleton class might be used by the whole application in the same way
3) It is a FINAL class
4) Should the clients of this class be unaware of the application they are part of?
Why we should be extremely sure about using a Singleton??,
1) One of the main things is the Liskov Substitution Principle
Let see it with an example, let's suppose you have the following class structure:
Let's also say that A is a helper (or utility class). Some common thought it to implement the helper as a singleton so we don't have an instance for each client so the code gains in performance (which is not very good, we should not consider performance in our design unless performance is our problem). Now, someone comes in the future and realizes that the way A should act depends on the business logic, so he decides to implement a new class that extends from A so he'll have something like:
His idea is quite good, but what's the problem he is facing right now?, he can't inject B or C to the client!! (we are violating LSP). As A is a Singleton, every time you do A.getInstance() you get a class of type A and nothing more, we cannot use LSP with Singleton pattern (this is something we agree to loose with this pattern, see point (3) ). Despite of the fact that we can't think about future changes while we are coding (one of the agile laws), when we implemented the helper as a singleton we didn't consider the first intention of the Singleton Pattern and this is when we made a mistake.
2) Let's think about unit test now, testing the client will be harder if we use a singleton as a Supplier. First of all, if you want to use a Singleton supplier, please, do it as the class diagram showed before. The cliente should have an instace, sorry..... THE instance of the Singleton Class. The client code should be like this:
public class Client
{
private A singletonA = A.getInstance();
public void useA()
{
singletonA.act();
}
{
private A singletonA = A.getInstance();
public void useA()
{
singletonA.act();
}
public void setSingletonA(A singletonA)
{
this.singletonA = singetonA;
}
}
IT MUST NOT BE LIKE THIS:
public class Client
{
public void useA()
{
A.getInstance().act()
}
}
{
public void useA()
{
A.getInstance().act()
}
}
Why?, well the first option can be tested with a mock, the second one doesn't.
Final comments
Singletons are good for they where created for, we shouldn't try to create a Singleton just because we think it should be there. We should think about the preconditions of the pattern, what it is supposed to solve?. Basically, we must consider if we NEED a single instance of the class. We must NOT consider if we THINK there should be a single instance of the class or if we THINK it would be better. Differencing this is the key part while we decide to implement a Singleton Pattern.
Thanks!
No comments:
Post a Comment