Tiny System Design - Design Patterns - Creational - Singleton

Tiny System Design - Design Patterns - Creational - Singleton

Read Part 1 here.

https://www.linkedin.com/posts/pillairajesh_tinysystemdesign-activity-7112844796683051008-w-Qq?utm_source=share&utm_medium=member_desktop

Welcome to part 2 and in this article, we will take a practical look at some simplified version of use cases where patterns shines.

Creational Patterns

We already know from part 1 that creational patterns helps is creating objects. Well that' easy said than done. When you want to create an object, but it’s complex or you want to have only one, or you want to decide what type to create at the last moment, you use these patterns. They help in the process of object creation while hiding the creation logic.

Let's begin with the Singleton Pattern.

Singleton

Definition

Ensure a class has only one instance and provide a global point of access to it.

 Frequency of use (in JavaScript):

●●●●● high

Motivation

It’s important for some classes (or equivalent types in non class based languages) to have exactly one instance.

Some examples for your kind perusal.

  • There should a single instance of URL router for your application (ideally)

  • Caching strategy design (ideally only one instance should be there)

  • Services Objects

How do we ensure that a class has only one instance and that the instance is easily accessible?

A global variable makes an object accessible, but it doesn’t keep you from instantiating multiple objects.

A better solution is to make the class itself responsible for keeping track of its sole instance.

The class can ensure that no other instance can be created (by intercepting requests to create new objects), and it can provide a way to access the instance. This is the Singleton pattern.

Points to Ponder

Singleton is not in a fundamental way inherently bad in the sense that anything in design or computing or technology can be good or bad (As you will hear and read a lot about bad things on singleton). The idea behind the design pattern series is you understand the core concepts, read other people’s opinion and then make a value judgement.

It’s not that if it didn’t worked for them, it may not work for you. Let’s get started. And also even if you don’t want to use the pattern, when you encounter them you know what you are dealing with rather than taking guess work.

Applicability

Use the Singleton pattern when

– There must be exactly one instance of a class, and it must be accessible to clients from a well known access point.

– When the sole instance should be extensible by sub-classing, and clients should be able to use an extended instance without modifying their code.

As you can observe by the above diagram a singleton class should have a public static method to create an instance (in this case the method name is instance(). Additionally it can have other methods.

Yet another conceptual diagram for more indepth understanding.

A note on code examples

I have purposefully kept code examples simple so that even beginner could follow.

Conceptual Code (Approach 1) – Object Literal

The quick way to create Singleton or Singleton like object in JavaScript is using Object Literal.

Conceptual Code (Approach 2) – Revealing Module Pattern (JavaScript)

Let’s use the Revealing Module Pattern to build up a structure for an image gallery. More about RMP will be covered separately.

Lets take a moment to look at how the client will use our ImageGallery code.

Conceptual Code (Approach 3) – Class + Symbol (JavaScript)

There are various ways to create a singleton class/function in javascript. Do note that we will use the ES6+ class notation for all examples. This will help you carry your understanding to other languages like c#, java etc (though not exactly but enough to understand other language nuisances and adapt as needed).

Here we will make use of the Symbol feature in JavaScript.

NOTE: (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol)

The data type symbol is a primitive data type. The Symbol() function returns a value of type symbol, has static properties that expose several members of built-in objects, has static methods that expose the global symbol registry, and resembles a built-in object class, but is incomplete as a constructor because it does not support the syntax “new Symbol()“.  

Every symbol value returned from Symbol() is unique.  A symbol value may be used as an identifier for object properties; this is the data type’s primary purpose, although other use-cases exist, such as enabling opaque data types, or serving as an implementation-supported unique identifier in general.

Conceptual Code -Singleton – Approach 1

Dry running/testing the code

(JavaScript) Practical Example – Singleton – Simple CacheManager

Let’s now take a look at a practical example of Singleton pattern in action by building a cache manager (key/value pair)

CacheManager Test Code

(Python) Practical Example – Singleton – Simple CacheManager

Python notes

  1. Used the method to implement the Singleton pattern in Python.

  2. Removed the explicit error for direct instantiation since the Singleton pattern is now handled by the method.

  3. Used Python's built-in dictionary methods for , , and .

(c#) Practical Example – Singleton – Simple CacheManager

C# Notes

  1. Used the type to implement the Singleton pattern in C#. This ensures thread safety and lazy initialization.

  2. Used C#'s for the cache storage.

  3. Used properties for and .

(Golang) Practical Example – Singleton – Simple CacheManager

Go Notes:

  1. Used the Singleton pattern in Go with the help of sync.Once to ensure that only one instance of CacheManager is created.

  2. Used Go's built-in map for cache storage.

  3. Added mutex locks (sync.RWMutex) to ensure thread safety when reading/writing to the cache.

Limitations of the pattern (adapted from web, from my peer groups)

  • People think it’s hard to test (but depends on your goal and testing strategy and tools).

  • Singletons’ create hidden dependencies (well not really if the purpose of singletons are made clear withing the working group members)

  • Singletons breaks OCP and SRP principles of SOLID (well again not really, as patterns always works best in groups rather than isolation. So based on needs you can bring in other patterns to fix the issue).

Applications

The following applications/areas uses Singleton or similar pattern extensively.

  • Game Programming (The Game Environment is usually a Singleton class which includes scores, list of enemies etc.

  • Service or Factory Objects in typical web applications (They are usually mixed with Dependency Injection.

  • Caching (Singleton or an adaptation of the pattern)

Related Patterns and principles

This section lists down patterns that makes singleton effective.

  • Factory Method

  • Dependency Inversion Principle (from SOLID principles)

To view or add a comment, sign in

Others also viewed

Explore topics