The Singleton pattern appeared, perhaps, as soon as static objects appeared. In Smalltalk-80, ChangeSet was made this way, and in a few different libraries sessions, statuses and similar objects began to appear, which were united by one thing - they should have been the only ones for the entire program.

In 1994, the famous book “Design Patterns” was published, presenting to the public, among 22 others, our hero, who was now called Singleton. There was also an implementation of it in C++, like this:

//.h class Singleton ( public: static Singleton* Instance(); protected: Singleton(); private: static Singleton* _instance; ) //.cpp Singleton* Singleton::_instance = 0; Singleton* Singleton::Instance() ( if(_instance == 0)( _instance = new Singleton; ) return _instance; )
As for flows, the authors don’t even write about them, considering this problem to be of little relevance. But we paid a lot of attention to all the subtleties of inheriting such classes from each other.

No wonder - it was 1995 and multitasking OS were too slow to bother anyone.

In any case, this code does not get old. Always use such an implementation if the class you want to declare will not be called from multiple threads.

In 1995, Scott Myers released his second book on C++ tricks. Among other things, he calls for using Singleton instead of static classes in order to save memory and know exactly when its constructor will be executed.

It was in this book that the canonical Myers singleton appeared and I see no reason not to present it here:
class singleton ( public: static singleton* instance() ( static singleton inst; return ) private: singleton() () );

The language standard is carefully, concisely and skillfully played out. A local static variable in a function will be called if and only if the function itself is called.

Then it was expanded, prohibiting a little more operations:

Class CMySingleton ( public: static CMySingleton& Instance() ( static CMySingleton singleton; return singleton; ) // Other non-static member functions private: CMySingleton() () // Private constructor ~CMySingleton() () CMySingleton(const CMySingleton&); // Prevent copy-construction CMySingleton& operator=(const CMySingleton&); // Prevent assignment );
According to the new C++11 standard, nothing more is needed to support threads. But we still have to wait until it is fully supported by all compilers.

In the meantime, for at least a decade and a half, the best minds have been trying to catch a multi-threaded singleton in the cage of language syntax. C++ did not support threads without third-party libraries - so very soon almost every library with threads had its own Singleton, which was “better than all others.” Alexandrescu devotes a whole chapter to them, domestic developers are fighting with him tooth and nail, and someone Andrei Nasonov also experiments for a long time and ultimately proposes... a completely different solution.

In 2004, Meyers and Alexandrescu joined forces and described Singleton with Double-check locking. The idea is simple - if the singleton is not detected in the first if, we make a lock, and check it again inside.

In the meantime, the problem of thread-safe Singleton has spread to other C-like languages. First - in Java, and then in C#. And now Jon Skeet offers a whole set of solutions, each of which has both pros and cons. And they are also offered by Microsoft.

For starters, the same option with double-check locking. Microsoft recommends writing it like this:
using System; public sealed class Singleton ( private static volatile Singleton instance; private static object syncRoot = new Object(); private Singleton() () public static Singleton Instance ( get ( if (instance == null) ( lock (syncRoot) ( if (instance == null) instance = new Singleton(); ) ) return instance; ) ) )

Skeet, however, thinks this code is bad. Why?

This doesn't work in Java. The Java memory model prior to version 1.5 did not check whether the constructor had completed execution before assigning a value. Fortunately, this is no longer relevant - Java 1.7 was released a long time ago, and Microsoft recommends this code and guarantees that it will work.
- It's easy to break. You get confused in the parentheses - that's all.
- Because of the lock it is quite slow
- There is better

There were also options without using streaming interfaces.

In particular, the well-known implementation is via a readonly field. According to Skeete (and Microsoft), this is the first option worth considering: Here's what it looks like:

Public sealed class Singleton ( private static readonly Singleton instance = new Singleton(); // Explicit static constructor to tell C# compiler // not to mark type as beforefieldinit static Singleton() ( ) private Singleton() ( ) public static Singleton Instance ( get (return instance; ) ) )

This option is also thread-safe and is based on the curious property of readonly fields - they are not initialized immediately, but on the first call. A wonderful idea, and the author himself recommends using it.

Does this implementation have any disadvantages? Of course yes:

If a class has static methods, then when they are called readonly, the field is initialized automatically.
- The constructor can only be static. This is a feature of the compiler - if the constructor is not static, then the type will be marked as beforefieldinit and readonly will be created simultaneously with the static ones.
- Static constructors of several related Singletons can accidentally loop each other, and then nothing will help and no one will save.

Finally, the famous lazy implementation with a nested class.
public sealed class Singleton ( private Singleton() ( ) public static Singleton Instance ( get ( return Nested.instance; ) ) private class Nested ( // Explicit static constructor to tell C# compiler // not to mark type as beforefieldinit static Nested() ( ) internal static readonly Singleton instance = new Singleton(); ) )

It has the same disadvantages as any other code that uses nested classes.

IN latest versions C# introduced the System.Lazy class, which encapsulates all this. This means the implementation has become even shorter:
public sealed class Singleton ( private static readonly Lazy lazy = new Lazy (() => new Singleton()); public static Singleton Instance ( get ( return lazy.Value; ) ) private Singleton() ( ) )

It is easy to see that both the readonly implementations, the variant with a nested class, and its simplification in the form of a lazy object do not work with threads. Instead, they use the language structures themselves, which “fool” the interpreter. This is their most important difference from double-lock, which works specifically with streams.

Why is it bad to “deceive” the tongue? Because every such “hack” is very easy to accidentally break. And because it is of no use to people who write in other languages ​​- but the pattern assumes universality.

Personally, I think that the thread problem should be solved using standard means. C# has many built-in classes and integers. keywords for working with multithreading. Why not use standard means, instead of trying to "trick" the compiler.

As I said, lock is not The best decision. The fact is that the compiler expands this lock(obj):

Lock(this) ( // other code )

Something like this code:

Boolean lockTaken = false; try ( Monitor.Enter(this, ref lockTaken); // other code ) finally ( if(lockTaken) Monitor.Exit(this); )

Jeffrey Richter considers this code to be very unfortunate. First of all, try is very slow. Secondly, if the try failed, then there is something wrong in the code. And when the second thread starts executing it, the error will most likely repeat itself. Therefore, he calls for using Monitor.Enter / Monitor.Exit for regular threads, and rewriting Singleton for atomic operations. Like this:

Public sealed class Singleton ( private static readonly Object s_lock = new Object(); private static Singleton instance = null; private Singleton() ( ) public static Singleton Instance ( get ( if(instance != null) return instance; Monitor.Enter( s_lock); Singleton temp = new Singleton(); Interlocked.Exchange(ref instance, temp); Monitor.Exit(s_lock); return instance; ) ) )

A temporary variable is needed because the C# standard requires the compiler to first create a variable and then assign it. As a result, it may turn out that instance is no longer null, but the initialization of the singleton has not yet been completed. See the description of similar cases in the 29th chapter of CLR via C# by Jeffrey Richter, section The Famous Double-Check Locking Technique.

Thus, there was a place for double-lock

Use this option for multi-threaded cases. It's simple, doesn't do anything poorly documented, is hard to break, and is easily portable to any language that has atomic operations.

A singleton is a pattern that belongs to the group of generating patterns (shiblons).

Purpose

Ensures that a class has only one instance (even more precisely we can say that "class of this type there can only be one copy") , and provides a global access point to it.

Nickname

The English name Singleton (singleton) is often translated into Russian-language texts and the Singleton pattern is called “Singleton”. We will use the Russian name as it is very successful.

Motivation

For some classes it is important that only one instance exists.
For example:

  1. Although there can be many printers in a system, only one spooler is possible.
  2. There should only be one file system and the only window manager.
  3. A digital filter can only contain one analog-to-digital converter (ADC). The accounting system serves only one company.

How to ensure that does the class have a single instance and that this instance is easily accessible?
A global variable gives access to an object, but does not prohibit instantiation of the class in several instances.
A better solution is achieved if the class itself:

  1. controls that it only has one instance
  2. can prevent the creation of additional instances by intercepting requests to create new objects
  3. and he is also able to provide access to his copy.

Known Applications

It is used in many systems that simulate real objects.

Related patterns

Many patterns can be implemented using the singleton pattern.
See description.

Many are already familiar with the term singleton. Briefly described, this is a pattern that describes an object that has a single instance. You can create such an instance different ways. But now we will not talk about this. I will also omit issues related to multithreading, although this is a very interesting and important issue when using this pattern. I would like to tell you about the correct use of singleton.

If you read the literature on this topic, you can find various criticisms of this approach. Here is a list of shortcomings:
  1. Singleton violates SRP (Single Responsibility Principle) - the Singleton class, in addition to fulfilling its immediate responsibilities, also controls the number of its instances.
  2. The dependency of a regular class on a singleton is not visible in the class's public contract. Since usually a singleton instance is not passed in method parameters, but is obtained directly, through getInstance(), to identify the class’s dependence on the singleton, you need to look into the body of each method - simply viewing the public contract of the object is not enough. As a consequence: the complexity of refactoring when subsequently replacing a singleton with an object containing several instances.
  3. Global state. It seems like everyone already knows about the harm of global variables, but here we have the same problem. When we access an instance of a class, we don't know the current state of that class or who changed it or when, and that state may not be what we expect. In other words, the correctness of working with a singleton depends on the order of calls to it, which causes an implicit dependence of the subsystems on each other and, as a result, seriously complicates development.
  4. The presence of a singleton reduces the testability of the application as a whole and of classes that use singletons in particular. Firstly, you cannot push a Mock object instead of a singleton, and secondly, if a singleton has an interface for changing its state, then the tests begin to depend on each other.
Thus, given these problems, many conclude that this pattern should be avoided. In general, I agree with the above issues, but I do not agree that these issues can lead to the conclusion that singletons should not be used. Let's take a closer look at what I mean and how you can avoid these problems even when using a singleton.

Implementation

The first thing I would like to note is that a singleton is an implementation, not an interface. What does it mean? This means that the class, if possible, should use a certain interface, otherwise it does not know and should not know whether there will be a singleton there or not, because any explicit use of a singleton will lead to the indicated problems. It looks good in words, let's see how it should look in life.

To implement this idea, we will use a powerful approach called Dependency Injection. Its essence is that we somehow pour the implementation into the class, while the class using the interface does not care about who will do it and when. He is not interested in these questions at all. All he needs to know is how to properly use the provided functionality. The interface of the functionality can be either an abstract interface or a concrete class. In our particular case, this does not matter.

We have an idea, let's implement it in C++. Templates and the possibility of their specialization will help us here. First, let's define a class that will contain a pointer to the required instance:
template struct An ( An() ( clear(); ) T* operator->() ( return get0(); ) const T* operator->() const ( return get0(); ) void operator=(T* t) ( data = t; ) bool isEmpty() const ( return data == 0; ) void clear() ( data = 0; ) void init() ( if (isEmpty()) reinit(); ) void reinit() ( anFill(*this); ) private: T* get0() const ( const_cast (this)->init(); return data; ) T* data; );
The described class solves several problems. First, it stores a pointer to the required instance of the class. Secondly, if there is no instance, the anFill function is called, which fills with the required instance in the absence of one (reinit method). When accessing a class, it is automatically initialized by an instance and called. Let's look at the implementation of the anFill function:
template void anFill(An & a) ( throw std::runtime_error(std::string("Cannot find implementation for interface: ") + typeid(T).name()); )
Thus by default this function throws an exception to prevent the use of an undeclared function.

Examples of using

Now let's say we have a class:
struct X ( X() : counter(0) () void action() ( std::cout<< ++ counter << ": in action" << std::endl; } int counter; };
We want to make it a singleton for use in different contexts. To do this, we specialize the anFill function for our class X:
template<>void anFill (An & a) ( static X x; a = )
In this case, we used the simplest singleton and for our reasoning the specific implementation does not matter. It is worth noting that this implementation is not thread-safe (multithreading issues will be discussed in another article). Now we can use class X like this:
An x; x->action();
Or simpler:
An ()->action();
What will be displayed on the screen:
1: in action
When we call action again we will see:
2: in action
Which means that we have saved state and exactly one instance of class X. Now let's complicate the example a little. To do this, let's create a new class Y, which will contain the use of class X:
struct Y ( An x; void doAction() ( x->action(); ) );
Now if we want to use the default instance, then we can simply do the following:
Y y; y.doAction();
Which after previous calls will display:
3: in action
Now suppose we wanted to use another instance of the class. This is very easy to do:
X x; y.x = y.doAction();
Those. we populate class Y with our (known) instance and call the appropriate function. On the screen we will get:
1: in action
Let's now look at the case of abstract interfaces. Let's create an abstract base class:
struct I ( virtual ~I() () virtual void action() = 0; );
Let's define 2 different implementations of this interface:
struct Impl1: I ( virtual void action() ( std::cout<< "in Impl1" << std::endl; } }; struct Impl2: I { virtual void action() { std::cout << "in Impl2" << std::endl; } };
By default, we will fill using the first implementation of Impl1:
template<>void anFill (An & a) ( static Impl1 i; a = )
So the following code:
An i; i->action();
Will give the output:
in Impl1
Let's create a class that uses our interface:
struct Z(An i; void doAction() ( i->action(); ) );
Now we want to change the implementation. Then we do the following:
Z z; Impl2 i; z.i = z.doAction();
What results:
in Impl2

Development of the idea

In general, this could be the end. However, it’s worth adding a few useful macros to make life easier:
#define PROTO_IFACE(D_iface) \ template<>void anFill (An & a) #define DECLARE_IMPL(D_iface) \ PROTO_IFACE(D_iface); #define BIND_TO_IMPL_SINGLE(D_iface, D_impl) \ PROTO_IFACE(D_iface) ( a = &single (); ) #define BIND_TO_SELF_SINGLE(D_impl) \ BIND_TO_IMPL_SINGLE(D_impl, D_impl)
Many people might say that macros are evil. I responsibly declare that I am familiar with this fact. However, it is part of the language and can be used, and I am not subject to dogma and prejudice.

The DECLARE_IMPL macro declares padding other than the default padding. In fact, this line says that this class will be automatically filled with a certain value in the absence of explicit initialization. The BIND_TO_IMPL_SINGLE macro will be used in the CPP file for implementation. It uses the single function, which returns a singleton instance:
template T& single() ( static T t; return t; )
Using the BIND_TO_SELF_SINGLE macro indicates that an instance of itself will be used for the class. Obviously, in the case of an abstract class, this macro is not applicable and you must use BIND_TO_IMPL_SINGLE to specify the class implementation. This implementation can be hidden and declared only in the CPP file.

Now let's look at the use using a specific example, for example, configuration:
// IConfiguration.hpp struct IConfiguration ( virtual ~IConfiguration() () virtual int getConnectionsLimit() = 0; virtual void setConnectionLimit(int limit) = 0; virtual std::string getUserName() = 0; virtual void setUserName(const std ::string& name) = 0; ); DECLARE_IMPL(IConfiguration) // Configuration.cpp struct Configuration: IConfiguration ( Configuration() : m_connectionLimit(0) () virtual int getConnectionsLimit() ( return m_connectionLimit; ) virtual void setConnectionLimit(int limit) ( m_connectionLimit = limit; ) virtual std: :string getUserName() ( return m_userName; ) virtual void setUserName(const std::string& name) ( m_userName = name; ) private: int m_connectionLimit; std::string m_userName; ); BIND_TO_IMPL_SINGLE(IConfiguration, Configuration);
Then you can use it in other classes:
struct ConnectionManager(An conf; void connect() ( if (m_connectionCount == conf->getConnectionsLimit()) throw std::runtime_error("Number of connections exceeds the limit"); ... ) private: int m_connectionCount; );

conclusions

As a result, I would note the following:
  1. Explicitly specifying a dependency on an interface: now there is no need to look for dependencies, they are all written in the class declaration and this is part of its interface.
  2. Providing access to the singleton instance and the class interface are separated into separate objects. In this way, everyone solves their problem, thereby maintaining SRP.
  3. If you have multiple configurations, you can easily upload the desired instance to the ConnectionManager class without any problems.
  4. Testability of the class: you can make a mock object and check, for example, whether the condition works correctly when calling the connect method:
    struct MockConfiguration: IConfiguration ( virtual int getConnectionsLimit() ( return 10; ) virtual void setConnectionLimit(int limit) ( throw std::runtime_error("not implemented in mock"); ) virtual std::string getUserName() ( throw std: :runtime_error("not implemented in mock"); ) virtual void setUserName(const std::string& name) ( throw std::runtime_error("not implemented in mock"); ) ); void test() ( // preparing ConnectionManager manager; MockConfiguration mock; manager.conf = // testing try ( manager.connect(); ) catch(std::runtime_error& e) ( //... ) )
Thus, the described approach eliminates the problems indicated at the beginning of this article. In subsequent articles, I would like to address important issues related to lifetime and multithreading.

22.10.2015
23:12

The purpose of the Singleton (or Singleton) pattern is to provide access to some unique object from anywhere in the application. Uniqueness means that such an object exists in memory in a single copy and other copies cannot be created.

Without the uniqueness condition, Singleton is an ordinary global variable, taking into account the resulting pros and cons (which are the majority). So before you use this pattern, make sure it really fits. The object that is supposed to be implemented as a Singleton must be truly unique at the system level.

Example implementation of the Singleton pattern in C++

Technically, implementing a Singleton object and using it in an application is quite simple (which is captivating):

#include class MySingleton ( public: // Member function for accessing a single instance static MySingleton* getInstance() ( static MySingleton instance; return ) // Fill it with useful functionality, like any other class void test() ( std::cout<< "Singleton test" << std::endl; } private: // Объявляем конструктор закрытым, чтобы нельзя было // создавать экземпляры класса извне MySingleton() { } }; int main() { // Используем Синглтон MySingleton::getInstance()->test(); // But this will not work, since the constructor is private // MySingleton singleton; return 0; )

If desired, a Singleton object can be adapted to a multi-threaded execution environment using mutexes.

Advertising

Always think before you create Singleton

It's tempting to have some object available anywhere in the program. But this violates many principles of creating good code. Therefore, do not rush to add Singletons, which complicate the program logic and introduce unnecessary dependencies.

Let's look at an example. It might seem like a good idea to create a class to manage application settings as a Singleton. Then all application components will be able to see the necessary options and use them easily. On the one hand, the idea seems pretty good. An application's configuration can indeed be represented by a unique entity. And free access to Singleton will simplify the use of the configuration.

However, in this case a serious problem arises. All components begin to depend on Singleton. If you need to transfer only one of the classes to another application, you will have to drag along with it Singleton, which can be designed to manage the parameters of dozens of other classes. It's better to spend a little more design time, but ensure that parameters are clearly passed to classes through their constructors, rather than through an inconspicuous Singleton.

In addition, the Singleton pattern complicates the use of polymorphism and other benefits of OOP, which may be needed when minimal refactoring is no longer sufficient.

Although there are quite harmless applications of Singletons. For example, when implementing another pattern: Abstract Factory.

Also, the use of Singleton is justified to represent physically unique computer resources. For example, it would be appropriate to implement a system for monitoring the connection/disconnection of USB devices in the form of a Singleton.

With this post I open a series of articles devoted to design patterns. Everything I have written is based solely on personal experience.

Design patterns are descriptions of some of the problems that arise during object-oriented design, as well as ways to solve them (both practical and theoretical). In other words, these are examples of correct approaches to solving typical design problems.

One of the most common patterns is Singleton. The purpose of this pattern is to limit the number of instances of a certain class within the application. Why might this be needed in practice? Read about this below. The plan for today is:

Simple Singleton Implementation

One of the simplest ways to implement the Singleton pattern in Java looks like this:

Public final class Singleton ( private static Singleton _instance = null; private Singleton() () public static synchronized Singleton getInstance() ( if (_instance == null) _instance = new Singleton(); return _instance; ) )

Now I will give some explanations about the implementation of the template.

The class constructor must be declared with the private visibility modifier. This will prevent instantiations of the class from being created either by the Singleton class or by its descendants. In this regard, you can safely add the final modifier to the class declaration.

The getInstance() method will create exactly one instance of the Singleton class. This method is declared as synchronized. This is why this was done. In multi-threaded programs, when multiple threads call the getInstance() method simultaneously, multiple instances of the Singleton class can be created. And there should only be one left!

You can get rid of the synchronized modifier. To do this, _instance needs to be initialized:

Private static final Singleton _instance = new Singleton(),

and in the getInstance() method remove the “if” construction. Then initialization will occur during class loading.

But using late initialization is preferable if creating an instance of a class takes a long time. And even in the case of lazy initialization, it is possible to handle exceptional situations that arise when calling the constructor.

Singleton with double-checked locking

The only problem with lazy initialization is that synchronization is only needed once, so that several threads do not enter the critical section at the same time. But after creating an instance of the class, I would like to get rid of synchronization.

The most common way to get rid of unnecessary synchronization is double-checked locking, which looks like this:

Public final class Singleton ( private static volatile Singleton _instance = null; private Singleton() () public static synchronized Singleton getInstance() ( if (_instance == null) synchronized (Singleton.class) ( if (_instance == null) _instance = new Singleton(); ) return _instance; ) )

By the way, before Java SE 1.5 this code did not work. If you want to know why, read.

Singleton with Instance Holder

Here is another noteworthy implementation of the Singleton pattern with lazy initialization:

Public final class Singleton ( private Singleton() () private static class Holder ( private static final Singleton _instance = new Singleton(); ) public static Singleton getInstance() ( return Holder._instance; ) )

The object will be initialized the first time the getInstance() method is called. That is, we moved the synchronization problem to the class loader level.

But what if the application has several Class Loaders or even we have a distributed system with several Java virtual machines? Then everything is complicated. Let's talk about this another time.

In general, it’s now fashionable to say that a really cool version of the Singleton pattern looks like this:

Public enum Singleton ( INSTANCE; )

That's all... Oh, yes! Why do we need this?

Practical Singleton Example

I find myself using this pattern most often when working with configuration. Sometimes it is convenient to store the program configuration in a file. Let's say this will be a simple text file "props.txt" with lines like "key=value". We need to ensure that the configuration in the program will be in a single copy. We wouldn’t have created the second one anyway, but we need to prohibit the user of the class from doing so. So,

Import java.util.*; import java.io.*; public class Configuration ( private static Configuration _instance = null; private Properties props = null; private Configuration() ( props = new Properties(); try ( FileInputStream fis = new FileInputStream(new File("props.txt")); props. load(fis); ) catch (Exception e) ( // handle error reading configuration ) ) public synchronized static Configuration getInstance() ( if (_instance == null) _instance = new Configuration(); return _instance; ) // get value properties by name public synchronized String getProperty(String key) ( String value = null; if (props.containsKey(key)) value = (String) props.get(key); else ( // report that the property was not found ) return value; ) )

Now to work with the configuration you can use a construction like:

String propValue = Configuration.getInstance().getProperty(propKey).

If the names of the properties in "props.txt" will not change, you can describe them in the class this way:

Public static final String PROP_KEY = "propKey",

and get the values ​​like this:

String propValue = Configuration.getInstance() .getProperty(Configuration.PROP_KEY).

The Singleton pattern is useful not only when working with configurations. It can also be used when writing ConnectionPool, Factory and other things.

That's all for sure now.