02

Design Pattern: Singleton

Es
Design Patterns Notes

One-Instance only Class.

Type: Creational.

Singleton UML
Singleton UML

Singletons can be useful for loggers, settings managers and any 1-instance patterns like façades or builders for example. An unknown provenance for the first invocation means that instantiation must be done automatically and the instance requires self-management. Also, holding global state in a singleton is a step better than polluting the global namespace.

Testing an implementation of this pattern or any processes that interacts with it and where data flows in both directions makes it difficult to test functionalities independently as a Singleton will retains state throughout its lifetime (i.e. between unit tests). A dirty solution is to implement some helper methods to set/clear that state which can then be called prior/post unit tests.

C++11

In C++11 a static local variable can be used safely in threaded environments.

class Singleton { public: ~Singleton() = default; Singleton & getInstance() { static Singleton instance; return instance; } private: Singleton() {} }

The C++11 standard (§6.7 [stmt.dcl] p4) states:

"If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization."

Java

In Java, for thread safety, double-checked locking can be used in getInstance() to ensure only 1 instance is created with lazy initialization (- where the object is created when getInstance() is first invoked and not before).

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

Alternatively, in order to avoid the synchronization overhead, initialization-on-demand holder idiom offers can be used instead.

public class Singleton { private Singleton() {} private static class LazyHolder { static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return LazyHolder.INSTANCE; } }