3 Ways to Implement the Singleton Pattern in TypeScript With Node.js
3 Ways to Implement the Singleton Pattern in TypeScript With Node.js
Choose which way works best for your needs.
Source: Unsplash
The singleton pattern is one of the most straightforward creational design patterns to implement. Aside from being easy to understand, it doesn’t require that many lines of code to write.
Throughout my career, I’ve come across code that uses different singleton implementation variations. I thought it would be great to compile these types of implementations in one article so that readers can use it as a reference in their future projects.
Singleton Review
Let’s start with a quick review of what problem a singleton pattern is trying to solve. A singleton pattern is used to maintain asingleinstance of an object without creating a new one — even if the instance is used in different parts of our application.
Singleton high-level diagram by the author.
This approach applies to object instantiations that you do not want to repeat. Some examples of implementations are logging, caching, and database connection.
We will use logging as an example in this article.
The Problem — Logging Example
Here’s an example problem: I have a Node.js app for payment processing that uses aLogger
class. We want to keep a single logger instance in this example and ensure theLogger
state is shared across the Payment app. To keep things simple, let’s say that we need to ensure that the logger needs to keep track of the total number of logged messages within the app. Ensuring that the counter is tracked globally within the app means that we will need a singleton class to achieve this.
A high-level diagram of the sample app by the author.
Let’s go through each of the classes that we will be using.
Logger class: Logger.ts
A basic logger class that allows its clients to log a message with a timestamp. It also allows the client to retrieve the total number of logged messages.
Payment class: Payment.ts
ThePayment
processing class processes the payment. It logs the payment instantiation and payment processing:
The entry point of the app: index.ts
The entry point creates an instance of theLogger
class and processes the payment. It also processes the payment through thePayment
class:
If we run the code above, we will get the following output:
# Run the app
tsc && node dist/creational/singleton/problem/index.js
Output screenshot by the author.
Notice that the log count stays at1
despite showing3
logged messages. The count remains at1
because a new instance ofLogger
is created inindex.ts
andPayment.ts
separately. The log count here only represents what’s logged inindex.ts
. However, we also want to include the number of logged messages in thePayment
class.
Here are different ways to solve this problem by using a singleton design pattern.
GitHub Repository (Optional)
If you want to follow along with the TyepScript code examples below, the code I’m using is available in the following GitHub repository:
Clone a local copy or run it directly in Gitpod.
Solution #1: Add a Separate Singleton Class
We can add aSingleton
class to the`