← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

Singleton (Anti-Pattern)

general Intermediate

Also Known As

singleton pattern single instance global instance

TL;DR

A class that restricts instantiation to a single instance — widely considered an anti-pattern due to hidden global state and testability issues.

Explanation

The Singleton pattern guarantees only one instance of a class exists and provides a global access point. While it solves real problems (single database connection, single logger), it introduces global state that makes classes dependent on Singleton internals, complicates testing (can't substitute mock implementations easily), and violates Dependency Inversion. The preferred alternative is using a Dependency Injection container to manage instance lifetime — register services as shared/singleton in the container, inject them via constructors.

Common Misconception

Singletons are a clean way to share a single instance across an application. Singletons are global state disguised as a pattern — they make unit testing nearly impossible (the instance persists between tests), hide dependencies, and create tight coupling. Dependency injection achieves the same single-instance goal without these problems.

Why It Matters

The Singleton pattern ensures one instance of a class exists globally — but it creates hidden global state that makes testing difficult and couples code to a specific implementation.

Common Mistakes

  • Using Singleton for services that should be injected — it prevents swapping implementations in tests.
  • Singleton that is not thread-safe in async or multi-process contexts.
  • Singletons that accumulate state across tests — tests must reset singleton state to be isolated.
  • Using Singleton when dependency injection containers already manage instance lifetime.

Code Examples

💡 Note
The Singleton itself isn't the problem — global mutable state is. Let a DI container manage instance lifetime instead.
✗ Vulnerable
class Config {
    private static ?self $instance = null;
    private function __construct() {}
    public static function getInstance(): self {
        self::$instance ??= new self();
        return self::$instance;
    }
    // Testing is impossible — can't inject a different Config
    // Shared mutable state across the application
}
✓ Fixed
// Use DI container to manage single instance instead
// config/app.php (Laravel service container)
$app->singleton(Config::class, fn() => new Config(getenv('APP_ENV')));

// Injected wherever needed — mockable in tests
class AppController {
    public function __construct(private Config $config) {}
}

Added 15 Mar 2026
Edited 22 Mar 2026
Views 20
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 1 ping M 0 pings T 0 pings W 2 pings T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 2 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S
No pings yet today
No pings yesterday
ChatGPT 4 Unknown AI 3 Google 3 Ahrefs 2 Perplexity 1
crawler 10 crawler_json 2 pre-tracking 1
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: High
⚡ Quick Fix
Replace Singletons with dependency injection — a DI container can manage single instances without the global state problem; Singleton makes testing impossible because you can't swap the instance
📦 Applies To
any web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
getInstance() static method; private constructor with static $instance; global state via Singleton breaking test isolation
Auto-detectable: ✓ Yes phpstan phpmd
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Medium ✗ Manual fix Fix: High Context: Class Tests: Update

✓ schema.org compliant