пятница, 19 сентября 2014 г.

When to use Singleton pattern?

Patterns I Hate #1: Singleton

Singleton Pattern

Use your singletons wisely

Difference between Singleton Pattern vs Static Class in Java

10 Singleton Pattern Interview questions in Java - Answered

Why Enum Singleton are better in Java

Singleton Pattern – Positive and Negative Aspects

This entry inaugurates a new series on patterns that I hate. Hate is a strong word, perhaps a better name would be “patterns that I’ve frequently seen lead to ruin”. But that seemed too long.
Anyhow, the singleton pattern is the hands-down #1 pattern that can lead me to froth at the mouth. When a programmer first stumbles on GoF, Singleton seems to be the pattern that they first latch on to because it’s so easy to understand (just one class). Novice programmers doing their first design will often break out subsystems and access them via singletons.
Why is Singleton evil?

Hides dependencies – A component that uses one or more singletons is hiding crucial information about your dependencies. It doesn’t take long for calls to a singleton to creep through your code base like kudzu, slowly attaching itself to every class in the system. Exposing that dependency forces you to think about it as you use a component. It also makes it more reusable as the caller can understand its requirements and how they might be satisfied.
Hard to test – The hidden coupling of users on a singleton makes testing a nightmare as there is no way to mock out or inject a test instance of the singleton. Also, the state of the singleton affects the execution of a suite of tests such that they are not properly isolated from each other.
Hard to subclass – Since initialization occurs in a singleton in static code, it is not amenable to subclassing because subclasses inherit the initialization code without the chance to override it.
It’s a lie! (in most Java systems) – Singletons in Java are based on static variables, which are held per-classloader, not per-VM. In most systems of any complexity these days (any based on an app server, OSGi, Eclipse, plugins, etc) many classloaders will be involved. In that case, it is quite easy for two plugins to create their own instance of a singleton. Sometimes this is done by design and is desirable. But it’s also easy to screw up. It’s also usually critical that the singleton get created in the right classloader, which can make lazily constructing the singleton tricky.
A singleton today is a multiple tomorrow – It’s not at all unusual to discover that you now need 2 or more of something you previously only needed one of. Hard-coding the singleton pattern into your code makes it impossible to satisfy that demand later. This probably seems really weird if it hasn’t happened to you, but it has happened more than once to me.
What is the alternative?

First, it is important to separate the “need for one of something in my system” from the “singleton pattern”. It’s perfectly reasonable to want one of something but to avoid using the singleton pattern. In other words, the problem is in the pattern, not in the goal.
When a singleton seems like the answer, I find it is often wiser to:
Create an interface and a default implementation of your singleton
Construct a single instance of your default implementation at the “top” of your system. This might be in a Spring config, or in code, or defined in a variety of ways depending on your system.
Pass the single instance into each component that needs it (dependency injection)
This alternative will give you the effects of a singleton, but makes the dependencies clear in the components that need it, allows a singleton to be mocked (via the interface), subclassed, proxied, and tested.
But I already have a bunch of singletons in my code!

Sometimes, you’ll have a system (built by you or someone else) that is heavily dependent on some singletons. Often, you will find this annoying as you try to test and/or add functionality to the system. To refactor the singletons out of your system, you need to start from each point of use and allow the singleton to be set as a dependency on the component using it, rather than calling to the singleton’s getInstance() method. Doing so moves the singleton access (but not use) up one level. Repeat until the singleton’s getInstance() method is called in as few places as possible (ideally one).

Example 1 - Logger Classes

The Singleton pattern is used in the design of logger classes. This classes are ussualy implemented as a singletons, and provides a global logging access point in all the application components without being necessary to create an object each time a logging operations is performed.

Example 2 - Configuration Classes

The Singleton pattern is used to design the classes which provides the configuration settings for an application. By implementing configuration classes as Singleton not only that we provide a global access point, but we also keep the instance we use as a cache object. When the class is instantiated( or when a value is read ) the singleton will keep the values in its internal structure. If the values are read from the database or from files this avoids the reloading the values each time the configuration parameters are used.

Example 3 - Accesing resources in shared mode

It can be used in the design of an application that needs to work with the serial port. Let's say that there are many classes in the application, working in an multi-threading environment, which needs to operate actions on the serial port. In this case a singleton with synchronized methods could be used to be used to manage all the operations on the serial port.

Example 4 - Factories implemented as Singletons

Let's assume that we design an application with a factory to generate new objects(Acount, Customer, Site, Address objects) with their ids, in an multithreading environment. If the factory is instantiated twice in 2 different threads then is possible to have 2 overlapping ids for 2 different objects. If we implement the Factory as a singleton we avoid this problem. Combining Abstract Factory or Factory Method and Singleton design patterns is a common practice.

Protected constructor

It is possible to use a protected constructor to in order to permit the subclassing of the singeton. This techique has 2 drawbacks that makes singleton inheritance impractical:
First of all, if the constructor is protected, it means that the class can be instantiated by calling the constructor from another class in the same package. A possible solution to avoid it is to create a separate package for the singleton.
Second of all, in order to use the derived class all the getInstance calls should be changed in the existing code from Singleton.getInstance() to NewSingleton.getInstance().

Singleton pattern and static class, former gives you an Object, while later just provide static methods. Since an object is always much more capable than a method, it can guide you when to use Singleton pattern vs static methods.

The following points are used against the Singleton pattern:

They deviate from the Single Responsibility Principle. A singleton class has the responsibility to create an instance of itself along with other business responsibilities. However, this issue can be solved by delegating the creation part to a factory object.
Singleton classes cannot be sub classed.
Singletons can hide dependencies. One of the features of an efficient system architecture is minimizing dependencies between classes. This will in turn help you while conducting unit tests and while isolating any part of the program to a separate assembly. A singleton will make you sacrifice this feature in your application. Since the object creation part is invisible to us, we cannot expect the singleton constructor to accept any parameters. This setback may look unimportant on the first glance but as the software complexity increases, it will limit the flexibility of the program.


Reduced memory footprint
Single point of access
Delayed initialization that prevents instantiation until required


Once instantiated, they're hardly ever "reset"
Harder to unit test and sometimes introduces hidden dependencies


Комментариев нет:

Отправить комментарий