AI Skill Report Card

Implementing Singleton Patterns

B+78·Feb 8, 2026·Source: Extension-page

Implementing Singleton Patterns in Java

Recommended: Enum Singleton (thread-safe by default)

Java
public enum ConfigSingleton { INSTANCE; private String config = "default"; public String getConfig() { return config; } public void setConfig(String config) { this.config = config; } } // Usage ConfigSingleton.INSTANCE.setConfig("production");

Alternative: Thread-safe Class Singleton

Java
public final class DatabaseSingleton { private static volatile DatabaseSingleton INSTANCE; private static final Object lock = new Object(); private DatabaseSingleton() {} public static DatabaseSingleton getInstance() { if (INSTANCE == null) { synchronized (lock) { if (INSTANCE == null) { INSTANCE = new DatabaseSingleton(); } } } return INSTANCE; } }
Recommendation
Add concrete input/output examples showing the actual behavior and state management of singleton instances across multiple calls

Choosing Implementation:

  • Use Enum Singleton - Default choice (thread-safe, serialization-safe)
  • Use Class Singleton - Only when enum constraints don't fit

For Class-Based Singleton:

  • Make constructor private
  • Create static volatile instance field
  • Implement double-checked locking in getInstance()
  • Mark class as final

For Enum Singleton:

  • Define single INSTANCE constant
  • Add private fields and methods as needed
  • No additional thread-safety code required
Recommendation
Include a template or framework section with ready-to-use singleton base classes or patterns for common use cases

Example 1: Configuration Manager

Java
public enum ConfigManager { INSTANCE; private Properties config = new Properties(); public void loadConfig(String filename) { // load properties } public String getProperty(String key) { return config.getProperty(key); } } // Usage ConfigManager.INSTANCE.loadConfig("app.properties"); String dbUrl = ConfigManager.INSTANCE.getProperty("db.url");

Example 2: Logger (Class-based)

Java
public final class Logger { private static volatile Logger INSTANCE; private static final Object lock = new Object(); private Logger() {} public static Logger getInstance() { if (INSTANCE == null) { synchronized (lock) { if (INSTANCE == null) { INSTANCE = new Logger(); } } } return INSTANCE; } public void log(String message) { System.out.println(new Date() + ": " + message); } }
Recommendation
Expand the edge cases section to cover classloader scenarios, serialization/deserialization behavior, and reflection attacks with concrete solutions
  • Prefer enum singletons - Built-in thread safety and serialization
  • Use volatile keyword for class-based instance fields
  • Implement double-checked locking to minimize synchronization overhead
  • Make constructor private and class final
  • Consider dependency injection instead of global singleton access
  • Pass singleton as parameter to methods rather than accessing globally

Thread Safety Issues:

Java
// WRONG: Not thread-safe public static ClassSingleton getInstance() { if (INSTANCE == null) { INSTANCE = new ClassSingleton(); // Race condition } return INSTANCE; } // WRONG: Synchronizing entire method (performance hit) public synchronized static ClassSingleton getInstance() { if (INSTANCE == null) { INSTANCE = new ClassSingleton(); } return INSTANCE; }

Design Issues:

  • Don't use singletons as global variables for mutable state
  • Avoid singletons that make unit testing difficult
  • Don't ignore classloader issues in distributed systems
  • Remember garbage collection can destroy unreferenced singletons

When NOT to use:

  • When you can pass dependencies as parameters
  • For configuration that needs different test/production values
  • In environments with multiple classloaders
  • When you need multiple instances later (violates Open/Closed principle)
0
Grade B+AI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
11/15
Workflow
11/15
Examples
15/20
Completeness
15/20
Format
11/15
Conciseness
11/15