Singleton Pattern with a Twist: Dual Instances in TypeScript
Mastering a Unique Singleton Design: Alternating Between Two Instances with Every Call
Problem
Implement the singleton pattern with a twist. First, instead of storing one instance, store two instances. And in every even call of getInstance(), return the first instance and in every odd call of getInstance(), return the second instance.
Problem Solution
In traditional singleton patterns, only one instance of a class is created and shared throughout the application. However, in this task, we need to implement a singleton pattern that alternates between two instances. On every even call to getInstance(), it should return the first instance, and on every odd call, it should return the second instance.
Step-by-Step Solution
Let’s break down the problem and implement the solution in TypeScript:
Class Structure:
- We’ll create a class named TwistedSingleton.
- Inside this class, we need two private static instance variables, instance1 and instance2, that will hold the two instances.
- A static variable callCount will be used to keep track of the number of times getInstance() is called.
Constructor:
- The constructor will be private to prevent direct instantiation.
getInstance Method:
- The getInstance() method will Increment the callCount and Return instance1 if callCount is even, or instance2 if callCount is odd.
- The first time the method is called, both instances will be created.
Implementation
Here’s how this could be implemented in TypeScript:
class TwistedSingleton {
// Static instances of the class
private static instance1: TwistedSingleton | null = null;
private static instance2: TwistedSingleton | null = null;
// Counter to keep track of the calls to getInstance()
private static callCount: number = 0;
// Private constructor to prevent direct instantiation
private constructor() {}
// Method to get the instance
public static getInstance(): TwistedSingleton {
// Increment call count
this.callCount++;
// Create instances if they don't exist
if (!this.instance1) {
this.instance1 = new TwistedSingleton();
}
if (!this.instance2) {
this.instance2 = new TwistedSingleton();
}
// Return instance1 if call count is even, instance2 if odd
if (this.callCount % 2 === 0) {
return this.instance1;
} else {
return this.instance2;
}
}
}
// Usage example
const instanceA = TwistedSingleton.getInstance();
const instanceB = TwistedSingleton.getInstance();
const instanceC = TwistedSingleton.getInstance();
console.log(instanceA === instanceB); // false (instanceA is instance1, instanceB is instance2)
console.log(instanceB === instanceC); // false (instanceB is instance2, instanceC is instance1)
console.log(instanceA === instanceC); // true (instanceA and instanceC are both instance1)
Explanation
- Initialization: When the class is first accessed via getInstance(), both instance1 and instance2 are created.
- Call Counting: The callCount variable ensures that the method alternates between returning instance1 and instance2.
- Instance Return: Depending on whether the callCount is odd or even, the method returns either instance1 or instance2.
Alternative Solutions
An alternative approach could involve using an array to store the instances and toggle between them using a modulus operation. However, this solution would not significantly differ in terms of efficiency or readability from the one provided above.
Conclusion
The dual-instance singleton pattern is a unique variation that allows alternating instances to be returned. This approach can be useful in scenarios where alternating resources or configurations are required.
This implementation provides a unique twist on the traditional singleton pattern, showcasing the flexibility and creativity that can be applied to classic design patterns.
Burhanuddin’s Code Compendium
Thank you for being a part of the Burhanuddin’s Code Compendium community! Before you go:
- Follow us: LinkedIn | YouTube| Newsletter
- Listen to our podcast on: Spotify| Amazon Music | Apple Podcasts
- More content at Burhanuddin’s Code Compendium