# Singleton

## Problem

You need exactly **one instance** of a class shared across the entire application — a config
manager, logging service, or connection pool. Multiple instances would cause inconsistencies,
resource waste, or data conflicts.

## Solution

Ensure a class has only one instance and provide a global point of access to it.
The class itself controls instantiation and returns the same instance on every request.

```
         ┌───────────────────┐
         │ ConfigManager      │
         │ -_instance: static │
         │ +getInstance()     │
         │ +get(key)          │
         │ +set(key, value)   │
         └───────────────────┘
              │
              │ always returns
              ▼ same instance
         ┌────────────────┐
         │ { db_host: ... }│
         │ { port: 8080 } │
         └────────────────┘
```

## When to Use

- There must be exactly one instance (hardware interface, thread pool, config store).
- The instance must be globally accessible.
- Lazy initialization is desired — create only when first needed.

## When to Avoid

**In most cases, prefer Dependency Injection over Singleton.** Singletons are problematic because:

- They introduce **hidden global state** that makes code hard to reason about.
- They make **unit testing extremely difficult** — you can't substitute mocks easily.
- They create **tight coupling** — every consumer depends on the concrete singleton class.
- They violate the **Single Responsibility Principle** — the class manages its own lifecycle.
- **Concurrency bugs** hide in lazy initialization without careful synchronization.

> **Rule of thumb**: If you're reaching for Singleton, first ask "Can I inject this instead?"
> See [Dependency Injection](dependency-injection.md) for the preferred approach.

## Pseudocode

```
class ConfigManager:
    static instance: ConfigManager = null
    field data: Map<string, string>

    private constructor():
        data = loadFromFile("config.json")

    static method getInstance() -> ConfigManager:
        if instance == null:
            instance = new ConfigManager()
        return instance

    method get(key) -> string:
        return data[key]

    method set(key, value):
        data[key] = value

// Usage
config = ConfigManager.getInstance()
config.set("db_host", "localhost")
// Anywhere else in the app:
same = ConfigManager.getInstance()  // same object
print(same.get("db_host"))  // "localhost"
```

## Python

```python
"""Singleton — ConfigManager using __new__."""


class ConfigManager:
    """Thread-safe singleton using __new__.

    NOTE: For production code, prefer dependency injection.
    This demonstrates the *pattern*, not a recommendation.
    """

    _instance: "ConfigManager | None" = None

    def __new__(cls) -> "ConfigManager":
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._instance._data: dict[str, str] = {}
            cls._instance._initialized = False
        return cls._instance

    def __init__(self) -> None:
        if not self._initialized:
            # Simulate loading config
            self._data = {"db_host": "localhost", "port": "5432"}
            self._initialized = True
            print("ConfigManager initialized (this happens only once)")

    def get(self, key: str, default: str = "") -> str:
        return self._data.get(key, default)

    def set(self, key: str, value: str) -> None:
        self._data[key] = value


if __name__ == "__main__":
    # First access — initializes
    config1 = ConfigManager()
    config1.set("db_host", "prod-db.example.com")
    print(f"config1.get('db_host') = {config1.get('db_host')}")

    # Second access — same instance
    config2 = ConfigManager()
    print(f"config2.get('db_host') = {config2.get('db_host')}")
    print(f"config1 is config2: {config1 is config2}")

    # ---- Why DI is better ----
    print("\n--- Why Dependency Injection is preferred ---")
    print("Problem: How do you test code that uses ConfigManager()?")
    print("  - You can't substitute a mock without monkey-patching.")
    print("  - Global state leaks between tests.")
    print("Solution: Pass config as a constructor argument instead.")
    print("  See dependency-injection.md for the full pattern.")

    print("\n--- Singleton demo complete ---")
```

## Go

```go
// singleton.go — ConfigManager using sync.Once
package main

import (
	"fmt"
	"sync"
)

// ConfigManager holds application configuration.
type ConfigManager struct {
	data map[string]string
}

var (
	configInstance *ConfigManager
	configOnce     sync.Once
)

// GetConfigManager returns the singleton instance.
// sync.Once guarantees thread-safe, one-time initialization.
func GetConfigManager() *ConfigManager {
	configOnce.Do(func() {
		fmt.Println("ConfigManager initialized (this happens only once)")
		configInstance = &ConfigManager{
			data: map[string]string{
				"db_host": "localhost",
				"port":    "5432",
			},
		}
	})
	return configInstance
}

func (c *ConfigManager) Get(key string) string {
	return c.data[key]
}

func (c *ConfigManager) Set(key, value string) {
	c.data[key] = value
}

func main() {
	// First access — initializes
	config1 := GetConfigManager()
	config1.Set("db_host", "prod-db.example.com")
	fmt.Printf("config1.Get(\"db_host\") = %s\n", config1.Get("db_host"))

	// Second access — same instance
	config2 := GetConfigManager()
	fmt.Printf("config2.Get(\"db_host\") = %s\n", config2.Get("db_host"))
	fmt.Printf("config1 == config2: %v\n", config1 == config2)

	// ---- Why DI is better ----
	fmt.Println("\n--- Why Dependency Injection is preferred ---")
	fmt.Println("Problem: How do you test code that calls GetConfigManager()?")
	fmt.Println("  - You can't substitute a mock without build tags or init tricks.")
	fmt.Println("  - sync.Once means you can't reset between tests.")
	fmt.Println("Solution: Accept a Config interface as a function/struct parameter.")
	fmt.Println("  See dependency-injection.md for the full pattern.")

	fmt.Println("\n--- Singleton demo complete ---")
}
```

## JavaScript

```javascript
// singleton.js — ConfigManager using module-scoped instance
//
// In JavaScript/Node.js, modules are cached after first evaluation,
// so exporting an instance IS effectively a singleton.

class ConfigManager {
  constructor() {
    // Guard against direct construction
    if (ConfigManager._instance) {
      return ConfigManager._instance;
    }
    this._data = { db_host: "localhost", port: "5432" };
    ConfigManager._instance = this;
    console.log("ConfigManager initialized (this happens only once)");
  }

  get(key) {
    return this._data[key] ?? "";
  }

  set(key, value) {
    this._data[key] = value;
  }
}

// --- Demo ---

// First access — initializes
const config1 = new ConfigManager();
config1.set("db_host", "prod-db.example.com");
console.log(`config1.get("db_host") = ${config1.get("db_host")}`);

// Second access — same instance
const config2 = new ConfigManager();
console.log(`config2.get("db_host") = ${config2.get("db_host")}`);
console.log(`config1 === config2: ${config1 === config2}`);

// ---- Why DI is better ----
console.log("\n--- Why Dependency Injection is preferred ---");
console.log("Problem: How do you test code that uses new ConfigManager()?");
console.log("  - You can't substitute a mock without module mocking hacks.");
console.log("  - Singleton state leaks between test files.");
console.log("Solution: Pass config as a constructor/function argument.");
console.log("  See dependency-injection.md for the full pattern.");

console.log("\n--- Singleton demo complete ---");
```

## Related Patterns

- **Dependency Injection** — prefer DI over singleton; DI achieves the same shared-instance goal without hidden global state or test difficulty.
- **Flyweight** — flyweight shares many instances of fine-grained objects; singleton ensures exactly one instance of a coarse-grained object.
- **Facade** — a facade is often implemented as a singleton providing a single entry point to a subsystem.
- **Monostate** — monostate (all instances share the same state) is an alternative to singleton that doesn't restrict instantiation.
