Creational Design Patterns provide solution to instantiate an object in the best possible way for specific situations. Following design patterns come under this category.
Singleton pattern ensures that only one object of a particular class is ever created.
Sometimes it’s important for some classes to have exactly one instance. There are many objects we only need one instance of them and if we, instantiate more than one, we’ll run into all sorts of problems like incorrect program behavior, overuse of resources, or inconsistent results.
Usually singletons are used for centralized management of internal or external resources and they provide a global point of access to themselves.
There are only two points in the definition of a singleton design pattern:
This sequence diagram shows how simple it is for a client to get an instance of the Singleton.
Usage of Singleton design pattern:
Java
// file Singleton.java class Singleton { private static Singleton instance; private Singleton() {} public static synchronized Singleton getInstance() { if (instance == null) instance = new Singleton(); return instance; } public void doSomething() { System.out.println("Singleton"); } // serialization protected Object readResolve() { return getInstance(); } } // file Demo.java public class Demo { public static void main(String[] args) { Singleton object = Singleton.getInstance(); object.doSomething(); } }
Python 3
Create Singleton using metaclass.
class SingletonType(type): instance = None def __call__(cls, *args, **kw): if not cls.instance: cls.instance = super(SingletonType, cls).__call__(*args, **kw) return cls.instance class Singleton(object): __metaclass__ = SingletonType def do_something(self): print('Singleton') s = Singleton() s.do_something()
Kotlin
Kotlin just introduces a reserved keyword for that. Behold, an object as follows:
object MySingelton{}
You don't need curly brackets there. They're just for visual consistency. This combines declaration and initialization in one keyword. From now on, MySingleton
can be accessed from anywhere in your code, and there'll be exactly one instance of it.
Of course, this object doesn't do anything interesting. Let's make it count the number of invocations instead:
object CounterSingleton { private val counter = AtomicInteger(0) fun increment() = counter.incrementAndGet() }
For now, we test it only to see how we call our Singleton:
for (i in 1..10) { println(CounterSingleton.increment()) }
This will print numbers between 1 and 10, as expected. As you can see, we don't need the getInstance()
method at all.
Objects can't have constructors. If you want some kind of initialization logic for your Singleton, such as loading data from the database or over the network for the first time, you can use the init
block instead:
object CounterSingleton { init { println("I was accessed for the first time") } // More code goes here }
It is also demonstrated that Singletons in Kotlin are initialized lazily, and not eagerly, as some could suspect from the ease of their declaration. Just like regular classes, objects can extend other classes and implement interfaces.
Swift
Let's look at how we implement the singleton pattern with Swift. The following code example shows how to create a singleton class:
class MySingleton { static let sharedInstance = MySingleton() var number = 0 private init() {} }
We can see that, within the MySingleton
class, we created a static constant named sharedInstance
, which contains an instance of the MySingleton
class. A static constant can be called without having to instantiate the class. Since we declared the sharedInstance
constant static, only one instance will exist throughout the lifecycle of the application, thereby creating the singleton pattern.
We also created the private initiator that will restrict other code from creating another instance of the MySingleton
class.
Now, let's see how this pattern works. The MySingleton
pattern has another property, named number
, which is an integer. We will monitor how this property changes as we use the sharedInstance
property to create multiple variables of the MySingleton
type, as shown in the following code:
var singleA = MySingleton.sharedInstance var singleB = MySingleton.sharedInstance var singleC = MySingleton.sharedInstance singleB.number = 2 print(singleA.number) print(singleB.number) print(singleC.number) singleC.number = 3 print(singleA.number) print(singleB.number) print(singleC.number)
In this example, we implemented the singleton pattern using a reference (class) type because we wanted to ensure that only one instance of the type existed throughout the application. If we implemented this pattern with a value type, such as a structure or an enumeration, we would run the risk of there being multiple instances of the type. If you recall, each time we pass an instance of a value type, we are actually passing a copy of that instance, which means that, if we implemented the singleton pattern with a value type, each time we called the sharedInstance
property we would receive a new copy, which would effectively break the singleton pattern.