Design patterns: Singleton

Design patterns (4 Part Series)

  1. Design patterns: Singleton
  2. Design patterns: Factory
  3. Design patterns: Observer
  4. Design patterns: Decorator

Hey guys, thanks for being here! I’ve decided to start writing some posts as I review design patterns. Design patterns help provide a general and reusable solution to recurring software development problems. First, we’re going to be taking a look at the singleton pattern.

Overview

  • Definition
  • Implementation
  • Real-world examples

Definition

Singleton: a single person or thing of the kind under consideration.

The singleton design pattern is a creational design pattern. It refers to a class that has only one instance in existence at any given time. If we try to instantiate a second instance of the singleton class, the new variable will also point to the first instance that was created earlier. Let’s take a look at the implementation of this pattern and then talk about some problems it can help solve.

Difference between singleton and conventional class
Difference between singleton and conventional class

Implementation

To achieve the singleton pattern, the class has two main characteristics:

  1. The constructor is private.
  2. There is a static method that returns the singleton instance.

These characteristics allow us to first create an instance for the class, if it has yet to be instantiated, and then return that instance whenever the class is called for.

Incorrect implementation

In the C# code below, when getObj() is called for the first time, it creates a Singleton obj and returns the same obj after that. This is not a thread-safe method; two threads running at the same time can create two objects for Singleton.

// This method is not thread-safe.
public sealed class Singleton
{
private static Singleton obj=null;
// private constructor.
private Singleton()
{
}
// public static method for creating a single instance.
public static Singleton getObj
{
get
{
if (obj==null)
{
obj = new Singleton();
}
return obj;
}
}
}

Note that Singleton obj is created according to the requirement of the user. This is called lazy instantiation.

Correct implementation

Using C#, the actual pattern looks like this:

using System;
public class Program
{
public static void Main()
{
Singleton object1 = Singleton.Instance();
Singleton object2 = Singleton.Instance();
if (object1 == object2)
Console.WriteLine("They're the same instance!");
}
}
/// <summary>
/// The Singleton class.
/// </summary>
class Singleton
{
private static Singleton myInstance;
// 1. The constructor is private.
private Singleton() { }
// 2. Static method that returns the Singleton instance.
public static Singleton Instance()
{
if (myInstance == null)
myInstance = new Singleton();
return myInstance;
}
}

Real-Word Examples

Sweet, now we’re able to write a class that will only have one instance in our program at a time! What can we do with that? What kind of recurring software development problems can this pattern help solve?

A singleton pattern is especially useful when accessing some sort of resource that the entire application is making use of that may have issues when being accessed by more than one instance at a time (it helps solve concurrency issues). There are a lot of common development situations where this might be the case, like hardware interface access, and logging data to a file.

In the case of hardware interface access, we may be connecting to hardware that will have concurrency issues when being accessed by multiple instances. For example, the singleton pattern can help a printer print documents in a certain order to avoid deadlock situations. In the case of logging data to a file, we may have multiple clients logging to a single file at the same time. The singleton pattern can help prevent problems with concurrent access to this log file.

Disclaimer: There are a lot of resources for learning design patterns that can be implemented in different ways. I would recommend exploring more resources when finished with this post.

Attributions:
  1. undefined by undefined