Singleton pattern is a design pattern belonging to the creational group. Singleton ensures that only a single object of the class will be instantiated. Another important element of a Singleton is that an object is treated as a “global” variable, meaning that the object can be accessed from anywhere in the program.
When a class is built on the Singleton pattern, it can only be instantiated once. Any other initialization requests will be directed to the only object being instantiated. In addition, the object of a Singleton class will not be instantiated until it is actually used.
In this article, we will look at the idea, design, implementation, and application of this design pattern in details.
What is Singleton Pattern?
If you’re using windows, you’ve probably used the Control Panel before. Have you noticed that, if you are opening a Control Panel window, and then opening it again from somewhere else (for example, from the Start menu), you still only see a Control Panel window.
However, if you open Chrome, and then repeatedly click the Chrome shortcut from the Start menu or desktop, you will get a lot of different Chrome windows.
The Control Panel’s way of running programs can be seen as similar to the idea of the Singleton design pattern: only a single instance (object) is created when it is first needed. All subsequent accesses are directed to the created object.
On the other hand, the way to open multiple Chrome windows at the same time is similar to the way you create normal objects: from a class you create many objects to use.
You might ask the question, why limit creating a single object?
In programming, sometimes having a single, globally accessible object helps a lot. For example, you need to process the application’s configuration file, including reading the file, retrieving information, and saving the configuration. Since the configuration file is often unique, and needs to be accessed from many different places in the program, having a single, “global” object makes configuration access much simpler.
UML Design for Singleton Pattern
Compared to other design patterns, Single is much simpler, consisting of only a single class.
The singleton pattern applies to an existing class by making some adjustments:
Make the constructor private so that client code cannot instantiate objects of the class;
Add a public static member that returns an object of the class: This member will be accessed from the client code to get the object of the class;
Additional private static constructor: This constructor is responsible for initializing the static member of the class.
Singleton Pattern Implementation Example
Let’s implement this design pattern in C#:
using System; using static System.Console; namespace P01_Concept { public sealed class Singleton { private Singleton() { } static readonly Singleton _instance = new Singleton(); public static Singleton Instance => _instance; private int _count = 0; public void Increase() => _count++; public int Count => _count; } class Program { static void Main(string[] args) { Title = "SINGLETON DESIGN PATTERN"; WriteLine($"Start: {Singleton.Instance.Count}"); Singleton.Instance.Increase(); WriteLine($"First increment: {Singleton.Instance.Count}"); Singleton.Instance.Increase(); WriteLine($"Second increment: {Singleton.Instance.Count}"); Singleton.Instance.Increase(); WriteLine($"Third increment : {Singleton.Instance.Count}"); ReadKey(); } } }
In the program, we build the Singleton class according to the UML design:
- Singleton constructor set private;
- private static _instance variable contains object of the class;
- The static property Instance allows access to the _instance variable.
- In addition, the _count variable, the Increase method and the Count property are the same as in regular classes.
When you run the program, you get the following output:
Did you notice, the variable _count (and property Count) are normal member variables, which means it only exists when initializing the object. Each time the object is initialized, _count will again receive the value 0. The Increase method is a member method, so it only works on objects.
However, when the above program is run, the value of the _count variable is incremented exactly the same way it does on one object, not on many different objects. That means you actually only have one object of Singleton that is accessed via the Instance property.
With the above implementation you may be wondering, whether the two command lines:
static readonly Singleton _instance = new Singleton();
public static Singleton Instance => _instance;
Is it really only creating a single object when accessing the Instance property for the first time?
Do not worry. The variable _instance is actually a constant, of type runtime constant, although it is not declared with the const keyword. Runtime constant has the characteristic that it will be initialized only once, either in the constructor, or right at the declaration, and then never change the value again. That is, the object it contains will not change during the lifetime of the program.
Second, because it is a static “variable”, it is automatically initialized the first time the client code accesses it.
Since a Singleton cannot be a parent, it is also usually marked sealed.
Some Other Implementations of Singleton Pattern
Sometimes you also encounter the Singleton version like this:
public sealed class Singleton { private Singleton() { } static Singleton _instance; public static Singleton Instance => _instance ?? (_instance = new Singleton()); }
This implementation does not rely on the initialization characteristics of static members and readonly constants as above. Instead, when accessing the Instance, the property checks if its backing field, _instance, has been initialized. If _instance has already been initialized, the Instance property will return the value of _instance. Otherwise it just initializes the value for _instance. Therefore, the returned object is also unique.
Note, however, that this method of execution is not suitable for multithreaded (non-thread-safe) programs.
You may also encounter a more special version of the Singleton as follows:
public class Singleton { // Private constructor Singleton() { } // Nested class for lazy instantiation class SingletonCreator { static SingletonCreator() { } // Private object instantiated with private constructor internal static readonly Singleton uniqueInstance = new Singleton(); } // Public static property to get the object public static Singleton UniqueInstance { get { return SingletonCreator.uniqueInstance; } } }
The version is called lazy instantiation.
Conclusion
In this lesson, you have detailed the meaning and implementation of the singleton design pattern. This is a fairly simple design pattern but is very commonly used. Singleton is not only used independently, but often combined in some other design patterns (such as Builder, Prototype, Abstract Factory).
If you feel our website useful, before you leave please help the site with a small action so that it can grow and serve you better.
If you find above article useful, please help share it with everyone.
If you have any questions or comments, please write in the discussion section at the bottom of the page. Thanks for reading.