Статьи

Учебник по шаблону Singleton с примерами Java

Следующим паттерном в нашей серии является паттерн Синглтон. Синглтон, вероятно, является самым печально известным паттерном, поскольку его использование вызывает разрыв в сообществе разработчиков — некоторые говорят, что оно принадлежит, другие говорят, что оно против объектной ориентации.

Синглтоны в реальном мире 

В реальном мире синглтоны представляют собой нечто уникальное, поэтому в теории каждый человек является одиночкой. Если привести более конкретный пример, в вашем доме, вероятно, есть только один центральный электрический блок предохранителей. 

Refcard Designs Patterns
Для лучшего обзора самых популярных шаблонов
дизайна, лучше всего начать с Refcard Designs Patterns от DZone

Синглтон

Синглтон известен как шаблон творчества — он используется для конструирования объектов таким образом, чтобы их можно было отделить от внедряющей системы. Определение Синглтона, представленное в оригинальной книге «Банды четырех» на DesignPatterns, гласит: 

Убедитесь, что у класса есть только один экземпляр, и предоставьте ему глобальную точку доступа.

Across all 23 design patterns, the diagram definition of the Singleton pattern is the simplest:

 

We just provide one point of access to create an instance of the Singleton class. The constructor is kept private, giving the getInstance() method the responsibility of providing access to the Singleton.

 This sequence diagram shows how simple it is for a client to get an instance of the Singleton.

Where Would I Use This Pattern?

When you need to ensure there’s one instance of an object, available to a number of other classes, you may want to use the Singleton pattern. Singletons are used a lot where you need to provide a registry, or something like a thread pool. Logging is also another popular use of Singletons, providing one single access point to an applications log file.

So How Does It Work In Java?

This example will show how to put together the classic Singleton in Java, without thinking about the threading complications which we discuss later on in this article. 

The Singleton class has some characteristics that we generally want to ensure two things: 

  • We lazily load our singleton based on the first request for access to it.
  • There is no other way of instantiating our Singleton  

Keeping this in mind, here is our Java representation of a Singleton.

public class Singleton{    private Singleton instance;     private Singleton()   {    }   public static Singleton getInstance()   {       if(instance==null)      {          instance = new Singleton();       }      return instance;   }}

We maintain the lazy loading principle here by only creating the instance when it is null, which will always be on the first call. Additionally, because we use a private constructor, we can only create the Singleton by calling the getInstance() method. 

For completeness, here is how a client can access the Singleton:

//access the singletonSingleton singleton = Singleton.getInstance();//use the singleton

As you can see, it’s fairly simple — but there are downsides.

Watch Out for the Downsides

As I mentioned at the beginning of this article, the Singleton is infamous in object oriented systems. A lot of the time the Singleton is used as a shortcut, so that the designer doesn’t need to think properly about object visibility. If you’re hacking in a Singleton so that there is global access to a resource, maybe it’s not the right thing to do. It might be better to work out how to pass the reference to that resource around properly.

Another important consideration is multi-threading. If two threads call the getInstance() method at the same time, you can end up with two singletons. Making the getInstance() method synchronised solves this issue, but then you have the performance cost — calling a synchronised version of getInstance() will be slower than the non-synchronized version.  However, maybe the best way around this is to sacrifice lazy-loading in the Singleton, ensuring there can only ever be on instance. A number of alternatives are listed here

Google have even provided a Singleton Detector, to discourage their use in programs. The page «Why Singletons are Controversial» gives another good overview on the pitfalls around the pattern.

First, programs using global state are very difficult to test. …the singleton user and the singleton become inextricably coupled together. It is no longer possible to test the user without also testing the singleton.
…..
Second, programs that rely on global state hide their dependencies.

If you’ve been following this series you’ll notice that no other pattern has had so many downsides and cautionary notes. It’s true for all patterns that you need to carefully consider it’s applicability to your problem before using it. With Singleton, consider it twice as much.

Next Up

Later this week, we’ll be taking a look at another creational pattern —  the Factory pattern.

Enjoy the Whole «Design Patterns Uncovered» Series:

Creational Patterns

Structural Patterns

Behavioral Patterns