The Dev Journey

Singleton Design Pattern using Typescript

The Singleton design pattern is a creational pattern that ensures a class has only one instance while providing a global point of access to that instance. This is useful when exactly one object is needed to coordinate actions across the system.

Key Points:

  1. Single Instance: Ensures that a class has only one instance.
  2. Global Access: Provides a global point of access to the instance.
  3. Lazy Initialization: The instance is created only when it is needed.

When to Use:

  • Logging: A single logging instance to manage logs across the application.
  • Configuration: A single configuration instance to manage application settings.
  • Database Connection: A single database connection instance to manage database operations.
  • Thread Pool: A single thread pool instance to manage threads.

Example in TypeScript:

class Singleton {
    private static instance: Singleton;
    private constructor() {
        // Initialization code here
    }

    public static getInstance(): Singleton {
        if (!Singleton.instance) {
            Singleton.instance = new Singleton();
        }
        return Singleton.instance;
    }

    public someMethod(): void {
        console.log("Method called on the singleton instance.");
    }
}

// Usage
const singletonInstance1 = Singleton.getInstance();
const singletonInstance2 = Singleton.getInstance();

if (singletonInstance1 === singletonInstance2) {
    console.log("Both instances are the same.");
}

singletonInstance1.someMethod();

Explanation:

  1. Private Constructor: The constructor is private to prevent direct instantiation.
  2. Static Instance: A static variable instance holds the single instance of the class.
  3. getInstance Method: The getInstance method checks if the instance is already created. If not, it creates one and returns it.

Use Cases:

  1. Logging:
class Logger {
    private static instance: Logger;
    private constructor() {
        // Initialization code here
    }

    public static getInstance(): Logger {
        if (!Logger.instance) {
            Logger.instance = new Logger();
        }
        return Logger.instance;
    }

    public log(message: string): void {
        console.log(`LOG: ${message}`);
    }
}

// Usage
const logger = Logger.getInstance();
logger.log("This is a log message.");

2.Configuration:

class Config {
    private static instance: Config;
    private settings: { [key: string]: any };

    private constructor() {
        this.settings = {};
    }

    public static getInstance(): Config {
        if (!Config.instance) {
            Config.instance = new Config();
        }
        return Config.instance;
    }

    public set(key: string, value: any): void {
        this.settings[key] = value;
    }

    public get(key: string): any {
        return this.settings[key];
    }
}

// Usage
const config = Config.getInstance();
config.set("apiUrl", "https://api.example.com");
console.log(config.get("apiUrl"));

3. Database Connection:

class Database {
    private static instance: Database;
    private connection: any;

    private constructor() {
        this.connection = this.createConnection();
    }

    public static getInstance(): Database {
        if (!Database.instance) {
            Database.instance = new Database();
        }
        return Database.instance;
    }

    private createConnection(): any {
        // Logic to create a database connection
        return {};
    }

    public getConnection(): any {
        return this.connection;
    }
}

// Usage
const db = Database.getInstance();
const connection = db.getConnection();

The Singleton pattern is useful for scenarios where a single instance of a class is required to manage shared resources or coordinate actions across the system. It ensures that the instance is created only once and provides a global point of access to it.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *